aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/protobuf/java
diff options
context:
space:
mode:
authorGravatar Jakob Buchgraber <buchgr@google.com>2017-04-12 14:30:38 +0200
committerGravatar Jakob Buchgraber <buchgr@google.com>2017-04-14 14:06:29 +0200
commit5235d06159ba6fee412bee261ea7867d061252b0 (patch)
treed502ed5c8d15f750c8ca1eccc2cb929862dd0947 /third_party/protobuf/java
parent5bf9e0f225b4c1636e24782ef9043e6201a65188 (diff)
protobuf: Update protobuf to @laszlocsomor's master at commit 421d909.
Update protobuf to @laszlocsomor's fork of protobuf. This is essentially the development version of protobuf 3.2.0 and windows specific fixes from laszlo. Those fixes will be merged into protobuf soon: https://github.com/google/protobuf/pull/2969). For instructions on how to update protobuf for bazel see README.bazel.md. Change-Id: Ic1daafe30270cb6bcc6231e6c94fb670af0475e7
Diffstat (limited to 'third_party/protobuf/java')
-rw-r--r--third_party/protobuf/java/README.md127
-rw-r--r--third_party/protobuf/java/compatibility_tests/README.md50
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/deps/pom.xml43
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/pom.xml69
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto71
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto53
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto45
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto48
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto48
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto50
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto108
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto620
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto719
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto387
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto50
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto37
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto1046
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto64
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto51
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto40
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto42
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto360
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto43
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto72
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto52
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto61
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/pom.xml30
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/pom.xml71
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto71
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto53
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto45
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto48
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto48
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto50
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto108
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto620
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto719
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto387
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto50
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto37
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto1046
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto64
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto51
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto40
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto42
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto360
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto43
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto72
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto52
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto61
-rwxr-xr-xthird_party/protobuf/java/compatibility_tests/v2.5.0/test.sh140
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/pom.xml73
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java510
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java56
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java590
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java469
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java318
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java81
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java649
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java265
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java49
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java961
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java163
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java108
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java344
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java354
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java186
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java278
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java62
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java84
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java321
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java64
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java3068
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java536
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java438
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java153
-rw-r--r--third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java465
-rw-r--r--third_party/protobuf/java/core/generate-sources-build.xml20
-rw-r--r--third_party/protobuf/java/core/generate-test-sources-build.xml43
-rw-r--r--third_party/protobuf/java/core/pom.xml144
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessage.java649
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java383
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractParser.java258
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java180
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java51
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingService.java64
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java272
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java185
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteOutput.java116
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteString.java1558
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedInputStream.java2896
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java3001
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Descriptors.java2547
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java273
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/DynamicMessage.java684
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java66
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Extension.java86
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionLite.java63
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java396
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java95
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java227
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/FieldSet.java909
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/FloatArrayList.java272
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java3051
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java2421
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java2842
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/IntArrayList.java272
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Internal.java751
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java146
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyField.java154
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java437
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java423
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringList.java174
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/LongArrayList.java272
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java451
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntryLite.java226
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java625
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapFieldLite.java224
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Message.java292
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLite.java341
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java60
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java239
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java143
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageReflection.java990
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java48
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/NioByteString.java291
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Parser.java272
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java105
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java59
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java48
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java708
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java708
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RopeByteString.java897
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcCallback.java47
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcChannel.java71
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcController.java118
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcUtil.java136
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Service.java117
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/ServiceException.java52
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java241
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java241
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java673
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormat.java2108
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java137
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java226
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java104
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java99
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java1042
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java432
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java210
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java120
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java295
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java1573
-rw-r--r--third_party/protobuf/java/core/src/main/java/com/google/protobuf/WireFormat.java260
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java549
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/AnyTest.java137
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java458
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java100
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java80
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteStringTest.java772
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java141
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java971
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java795
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java79
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java819
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java461
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java324
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/EnumTest.java76
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java276
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java443
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java461
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java48
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java1674
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java461
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java186
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java448
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java246
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java120
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java335
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java363
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java130
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java125
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteTest.java2273
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java544
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java461
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java796
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java1178
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapTest.java1495
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/MessageTest.java351
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java183
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java619
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java271
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParserTest.java415
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java288
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java188
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java127
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java189
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/ServiceTest.java326
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java155
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java422
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java96
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtil.java3866
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtilLite.java559
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java182
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java86
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatTest.java1153
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java255
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java334
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java652
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java226
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java65
-rw-r--r--third_party/protobuf/java/core/src/test/java/com/google/protobuf/WireFormatTest.java604
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/any_test.proto42
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto94
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto71
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto81
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto121
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto120
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto61
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_test.proto110
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto78
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto54
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension.proto47
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto49
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto50
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto51
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto40
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto44
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto45
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto168
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto51
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto52
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto44
-rw-r--r--third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto61
-rw-r--r--third_party/protobuf/java/lite/generate-sources-build.xml20
-rw-r--r--third_party/protobuf/java/lite/generate-test-sources-build.xml43
-rw-r--r--third_party/protobuf/java/lite/pom.xml184
-rw-r--r--third_party/protobuf/java/pom.xml215
-rw-r--r--third_party/protobuf/java/util/pom.xml127
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Durations.java302
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java287
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java342
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java1766
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java400
-rw-r--r--third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Timestamps.java397
-rw-r--r--third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java261
-rw-r--r--third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java213
-rw-r--r--third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java1454
-rw-r--r--third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java498
-rw-r--r--third_party/protobuf/java/util/src/test/proto/com/google/protobuf/util/json_test.proto178
250 files changed, 98377 insertions, 0 deletions
diff --git a/third_party/protobuf/java/README.md b/third_party/protobuf/java/README.md
new file mode 100644
index 0000000000..0e0fba647a
--- /dev/null
+++ b/third_party/protobuf/java/README.md
@@ -0,0 +1,127 @@
+Protocol Buffers - Google's data interchange format
+===================================================
+
+[![Build Status](https://travis-ci.org/google/protobuf.svg?branch=master)](https://travis-ci.org/google/protobuf)
+
+Copyright 2008 Google Inc.
+
+This directory contains the Java Protocol Buffers runtime library.
+
+Installation - With Maven
+=========================
+
+The Protocol Buffers build is managed using Maven. If you would
+rather build without Maven, see below.
+
+1) Install Apache Maven if you don't have it:
+
+ http://maven.apache.org/
+
+2) Build the C++ code, or obtain a binary distribution of protoc (see
+ the toplevel [README.md](../README.md)). If you install a binary
+ distribution, make sure that it is the same version as this package.
+ If in doubt, run:
+
+ $ protoc --version
+
+ You will need to place the protoc executable in ../src. (If you
+ built it yourself, it should already be there.)
+
+3) Run the tests:
+
+ $ mvn test
+
+ If some tests fail, this library may not work correctly on your
+ system. Continue at your own risk.
+
+4) Install the library into your Maven repository:
+
+ $ mvn install
+
+5) If you do not use Maven to manage your own build, you can build a
+ .jar file to use:
+
+ $ mvn package
+
+ The .jar will be placed in the "target" directory.
+
+The above instructions will install 3 maven artifacts:
+
+ * protobuf-java: The core Java Protocol Buffers library. Most users only
+ need this artifact.
+ * protobuf-lite: The lite version of core Java Protobuf Buffers library. It
+ is a subset of the core library and is used together with
+ the 'lite' code generator flag to reduce generated code size
+ for mobile.
+ * protobuf-java-util: Utilities to work with protos. It contains JSON support
+ as well as utilities to work with proto3 well-known
+ types.
+
+Installation - Without Maven
+============================
+
+If you would rather not install Maven to build the library, you may
+follow these instructions instead. Note that these instructions skip
+running unit tests and only describes how to install the core protobuf
+library (without the util package).
+
+1) Build the C++ code, or obtain a binary distribution of protoc. If
+ you install a binary distribution, make sure that it is the same
+ version as this package. If in doubt, run:
+
+ $ protoc --version
+
+ If you built the C++ code without installing, the compiler binary
+ should be located in ../src.
+
+2) Invoke protoc to build DescriptorProtos.java:
+
+ $ protoc --java_out=core/src/main/java -I../src \
+ ../src/google/protobuf/descriptor.proto
+
+3) Compile the code in core/src/main/java using whatever means you prefer.
+
+4) Install the classes wherever you prefer.
+
+Compatibility Notice
+====================
+
+* Protobuf minor version releases are backwards-compatible. If your code
+ can build/run against the old version, it's expected to build/run against
+ the new version as well. Both binary compatibility and source compatibility
+ are guaranteed for minor version releases if the user follows the guideline
+ described in this section.
+
+* Protobuf major version releases may also be backwards-compatbile with the
+ last release of the previous major version. See the release notice for more
+ details.
+
+* APIs marked with the @ExperimentalApi annotation are subject to change. They
+ can be modified in any way, or even removed, at any time. Don't use them if
+ compatibility is needed. If your code is a library itself (i.e. it is used on
+ the CLASSPATH of users outside your own control), you should not use
+ experimental APIs, unless you repackage them (e.g. using ProGuard).
+
+* Deprecated non-experimental APIs will be removed two years after the release
+ in which they are first deprecated. You must fix your references before this
+ time. If you don't, any manner of breakage could result (you are not
+ guaranteed a compilation error).
+
+* Protobuf message interfaces/classes are designed to be subclassed by protobuf
+ generated code only. Do not subclass these message interfaces/classes
+ yourself. We may add new methods to the message interfaces/classes which will
+ break your own subclasses.
+
+* Don't use any method/class that is marked as "used by generated code only".
+ Such methods/classes are subject to change.
+
+* Protobuf LITE runtime APIs are not stable yet. They are subject to change even
+ in minor version releases.
+
+Documentation
+=============
+
+The complete documentation for Protocol Buffers is available via the
+web at:
+
+ https://developers.google.com/protocol-buffers/
diff --git a/third_party/protobuf/java/compatibility_tests/README.md b/third_party/protobuf/java/compatibility_tests/README.md
new file mode 100644
index 0000000000..72c6034c99
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/README.md
@@ -0,0 +1,50 @@
+# Protobuf Java Compatibility Tests
+
+This directory contains tests to ensure protobuf library is compatible with
+previously released versions.
+
+## Directory Layout
+
+For each released protobuf version we are testing compatibility with, there
+is a sub-directory with the following layout (take v2.5.0 as an example):
+
+ * v2.5.0
+ * test.sh
+ * pom.xml
+ * protos/ - unittest protos.
+ * more_protos/ - unittest protos that import the ones in "protos".
+ * tests/ - actual Java test classes.
+
+The testing code is extracted from regular protobuf unittests by removing:
+
+ * tests that access package private methods/classes.
+ * tests that are known to be broken by an intended behavior change (e.g., we
+ changed the parsing recursion limit from 64 to 100).
+ * all lite runtime tests.
+
+It's also divided into 3 submodule with tests depending on more_protos and
+more_protos depending on protos. This way we can test scenarios where only part
+of the dependency is upgraded to the new version.
+
+## How to Run The Tests
+
+We use a shell script to drive the test of different scenarios so the test
+will only run on unix-like environments. The script expects a few command
+line tools to be available on PATH: git, mvn, wget, grep, sed, java.
+
+Before running the tests, make sure you have already built the protoc binary
+following [the C++ installation instructions](../../src/README.md). The test
+scripts will use the built binary located at ${protobuf}/src/protoc.
+
+To start a test, simply run the test.sh script in each version directory. For
+example:
+
+ $ v2.5.0/test.sh
+
+For each version, the test script will test:
+
+ * only upgrading protos to the new version
+ * only upgrading more_protos to the new version
+
+and see whether everything builds/runs fine. Both source compatibility and
+binary compatibility will be tested.
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/deps/pom.xml b/third_party/protobuf/java/compatibility_tests/v2.5.0/deps/pom.xml
new file mode 100644
index 0000000000..7ceb96049d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/deps/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-test-deps</artifactId>
+ <version>2.5.0</version>
+
+ <name>Compatibility Test Dependencies</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/pom.xml b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/pom.xml
new file mode 100644
index 0000000000..ff0c4133f0
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-test-suite</artifactId>
+ <version>2.5.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-more-protos</artifactId>
+ <version>2.5.0</version>
+
+ <name>More protos for Compatibility test</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>${more_protos.protobuf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-protos</artifactId>
+ <version>2.5.0</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.3</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="target/generated-sources" />
+ <exec executable="${more_protos.protoc.path}">
+ <arg value="--java_out=target/generated-sources" />
+ <arg value="--proto_path=src/proto" />
+ <arg value="src/proto/google/protobuf/unittest.proto" />
+ <arg value="src/proto/google/protobuf/unittest_optimize_for.proto" />
+ <arg value="src/proto/com/google/protobuf/multiple_files_test.proto" />
+ </exec>
+ </tasks>
+ <sourceRoot>target/generated-sources</sourceRoot>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto
new file mode 100644
index 0000000000..9a040145a6
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/multiple_files_test.proto
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// A proto file which tests the java_multiple_files option.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "MultipleFilesTestProto";
+
+message MessageWithNoOuter {
+ message NestedMessage {
+ optional int32 i = 1;
+ }
+ enum NestedEnum {
+ BAZ = 3;
+ }
+ optional NestedMessage nested = 1;
+ repeated TestAllTypes foreign = 2;
+ optional NestedEnum nested_enum = 3;
+ optional EnumWithNoOuter foreign_enum = 4;
+}
+
+enum EnumWithNoOuter {
+ FOO = 1;
+ BAR = 2;
+}
+
+service ServiceWithNoOuter {
+ rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
+}
+
+extend TestAllExtensions {
+ optional int32 extension_with_outer = 1234567;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto
new file mode 100644
index 0000000000..abffb9d2ba
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_builders_test.proto
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+//
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "NestedBuilders";
+
+
+message Vehicle {
+ optional Engine engine = 1;
+ repeated Wheel wheel = 2;
+}
+
+message Engine {
+ optional int32 cylinder = 1;
+ optional int32 liters = 2;
+}
+
+message Wheel {
+ optional int32 radius = 1;
+ optional int32 width = 2;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto
new file mode 100644
index 0000000000..9fe5d560c9
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions. Note that this must be defined in
+// a separate file to properly test the initialization of the outer class.
+
+
+import "com/google/protobuf/non_nested_extension.proto";
+
+package protobuf_unittest;
+
+message MyNestedExtension {
+ extend MessageToBeExtended {
+ optional MessageToBeExtended recursiveExtension = 2;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto
new file mode 100644
index 0000000000..16ee46e57d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/nested_extension_lite.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions for a MessageLite messages. Note that
+// this must be defined in a separate file to properly test the initialization
+// of the outer class.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+import "com/google/protobuf/non_nested_extension_lite.proto";
+
+message MyNestedExtensionLite {
+ extend MessageLiteToBeExtended {
+ optional MessageLiteToBeExtended recursiveExtensionLite = 3;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto
new file mode 100644
index 0000000000..f61b419bc2
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions.
+
+
+package protobuf_unittest;
+
+message MessageToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtension {
+}
+
+extend MessageToBeExtended {
+ optional MyNonNestedExtension nonNestedExtension = 1;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
new file mode 100644
index 0000000000..3c82659b5e
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions for a MessageLite messages.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message MessageLiteToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtensionLite {
+}
+
+extend MessageLiteToBeExtended {
+ optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
new file mode 100644
index 0000000000..6e67d97a69
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the java code generator.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+package io_protocol_tests;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TestBadIdentifiersProto";
+
+message TestMessage {
+}
+
+message Descriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ message NestedDescriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ }
+ optional NestedDescriptor nested_descriptor = 2;
+}
+
+message Parser {
+ enum ParserEnum {
+ PARSER = 1;
+ }
+ optional ParserEnum parser = 1;
+}
+
+message Deprecated {
+ enum TestEnum {
+ FOO = 1;
+ }
+
+ optional int32 field1 = 1 [deprecated=true];
+ optional TestEnum field2 = 2 [deprecated=true];
+ optional TestMessage field3 = 3 [deprecated=true];
+}
+
+message Override {
+ optional int32 override = 1;
+}
+
+message Object {
+ optional int32 object = 1;
+ optional string string_object = 2;
+}
+
+message String {
+ optional string string = 1;
+}
+
+message Integer {
+ optional int32 integer = 1;
+}
+
+message Long {
+ optional int32 long = 1;
+}
+
+message Float {
+ optional float float = 1;
+}
+
+message Double {
+ optional double double = 1;
+}
+
+service TestConflictingMethodNames {
+ rpc Override(TestMessage) returns (TestMessage);
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto
new file mode 100644
index 0000000000..a785f79faf
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/descriptor.proto
@@ -0,0 +1,620 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+
+package google.protobuf;
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+ repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+ optional string name = 1; // file name, relative to root of source tree
+ optional string package = 2; // e.g. "foo", "foo.bar", etc.
+
+ // Names of files imported by this file.
+ repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
+
+ // All top-level definitions in this file.
+ repeated DescriptorProto message_type = 4;
+ repeated EnumDescriptorProto enum_type = 5;
+ repeated ServiceDescriptorProto service = 6;
+ repeated FieldDescriptorProto extension = 7;
+
+ optional FileOptions options = 8;
+
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field whithout harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ optional SourceCodeInfo source_code_info = 9;
+}
+
+// Describes a message type.
+message DescriptorProto {
+ optional string name = 1;
+
+ repeated FieldDescriptorProto field = 2;
+ repeated FieldDescriptorProto extension = 6;
+
+ repeated DescriptorProto nested_type = 3;
+ repeated EnumDescriptorProto enum_type = 4;
+
+ message ExtensionRange {
+ optional int32 start = 1;
+ optional int32 end = 2;
+ }
+ repeated ExtensionRange extension_range = 5;
+
+ optional MessageOptions options = 7;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+ enum Type {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ TYPE_DOUBLE = 1;
+ TYPE_FLOAT = 2;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
+ TYPE_UINT64 = 4;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
+ TYPE_FIXED64 = 6;
+ TYPE_FIXED32 = 7;
+ TYPE_BOOL = 8;
+ TYPE_STRING = 9;
+ TYPE_GROUP = 10; // Tag-delimited aggregate.
+ TYPE_MESSAGE = 11; // Length-delimited aggregate.
+
+ // New in version 2.
+ TYPE_BYTES = 12;
+ TYPE_UINT32 = 13;
+ TYPE_ENUM = 14;
+ TYPE_SFIXED32 = 15;
+ TYPE_SFIXED64 = 16;
+ TYPE_SINT32 = 17; // Uses ZigZag encoding.
+ TYPE_SINT64 = 18; // Uses ZigZag encoding.
+ };
+
+ enum Label {
+ // 0 is reserved for errors
+ LABEL_OPTIONAL = 1;
+ LABEL_REQUIRED = 2;
+ LABEL_REPEATED = 3;
+ // TODO(sanjay): Should we add LABEL_MAP?
+ };
+
+ optional string name = 1;
+ optional int32 number = 3;
+ optional Label label = 4;
+
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
+ optional Type type = 5;
+
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ optional string type_name = 6;
+
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ optional string extendee = 2;
+
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ optional string default_value = 7;
+
+ optional FieldOptions options = 8;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+ optional string name = 1;
+
+ repeated EnumValueDescriptorProto value = 2;
+
+ optional EnumOptions options = 3;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+ optional string name = 1;
+ optional int32 number = 2;
+
+ optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+ optional string name = 1;
+ repeated MethodDescriptorProto method = 2;
+
+ optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+ optional string name = 1;
+
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ optional string input_type = 2;
+ optional string output_type = 3;
+
+ optional MethodOptions options = 4;
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached. These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them. Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+// organization, or for experimental options, use field numbers 50000
+// through 99999. It is up to you to ensure that you do not use the
+// same number for multiple options.
+// * For options which will be published and used publicly by multiple
+// independent entities, e-mail protobuf-global-extension-registry@google.com
+// to reserve extension numbers. Simply provide your project name (e.g.
+// Object-C plugin) and your porject website (if available) -- there's no need
+// to explain how you intend to use them. Usually you only need one extension
+// number. You can declare multiple options with only one extension number by
+// putting them in a sub-message. See the Custom Options section of the docs
+// for examples:
+// http://code.google.com/apis/protocolbuffers/docs/proto.html#options
+// If this turns out to be popular, a web service will be set up
+// to automatically assign option numbers.
+
+
+message FileOptions {
+
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ optional string java_package = 1;
+
+
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ optional string java_outer_classname = 8;
+
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ optional bool java_multiple_files = 10 [default=false];
+
+ // If set true, then the Java code generator will generate equals() and
+ // hashCode() methods for all messages defined in the .proto file. This is
+ // purely a speed optimization, as the AbstractMessage base class includes
+ // reflection-based implementations of these methods.
+ optional bool java_generate_equals_and_hash = 20 [default=false];
+
+ // Generated classes can be optimized for speed or code size.
+ enum OptimizeMode {
+ SPEED = 1; // Generate complete code for parsing, serialization,
+ // etc.
+ CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
+ LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+ }
+ optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. There is no default.
+ optional string go_package = 11;
+
+
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of proto2.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ optional bool cc_generic_services = 16 [default=false];
+ optional bool java_generic_services = 17 [default=false];
+ optional bool py_generic_services = 18 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MessageOptions {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ optional bool message_set_wire_format = 1 [default=false];
+
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message FieldOptions {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ optional CType ctype = 1 [default = STRING];
+ enum CType {
+ // Default mode.
+ STRING = 0;
+
+ CORD = 1;
+
+ STRING_PIECE = 2;
+ }
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob.
+ optional bool packed = 2;
+
+
+
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outher message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ optional bool lazy = 5 [default=false];
+
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ optional bool deprecated = 3 [default=false];
+
+ // EXPERIMENTAL. DO NOT USE.
+ // For "map" fields, the name of the field in the enclosed type that
+ // is the key for this map. For example, suppose we have:
+ // message Item {
+ // required string name = 1;
+ // required string value = 2;
+ // }
+ // message Config {
+ // repeated Item items = 1 [experimental_map_key="name"];
+ // }
+ // In this situation, the map key for Item will be set to "name".
+ // TODO: Fully-implement this, then remove the "experimental_" prefix.
+ optional string experimental_map_key = 9;
+
+ // For Google-internal migration only. Do not use.
+ optional bool weak = 10 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumOptions {
+
+ // Set this option to false to disallow mapping different tag names to a same
+ // value.
+ optional bool allow_alias = 2 [default=true];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumValueOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MethodOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+ // The name of the uninterpreted option. Each string represents a segment in
+ // a dot-separated name. is_extension is true iff a segment represents an
+ // extension (denoted with parentheses in options specs in .proto files).
+ // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+ // "foo.(bar.baz).qux".
+ message NamePart {
+ required string name_part = 1;
+ required bool is_extension = 2;
+ }
+ repeated NamePart name = 2;
+
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ optional string identifier_value = 3;
+ optional uint64 positive_int_value = 4;
+ optional int64 negative_int_value = 5;
+ optional double double_value = 6;
+ optional bytes string_value = 7;
+ optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ repeated Location location = 1;
+ message Location {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ repeated int32 path = 1 [packed=true];
+
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ repeated int32 span = 2 [packed=true];
+
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ optional string leading_comments = 3;
+ optional string trailing_comments = 4;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto
new file mode 100644
index 0000000000..6eb2d86f51
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest.proto
@@ -0,0 +1,719 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file we will use for unit testing.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true; // auto-added
+
+import "google/protobuf/unittest_import.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessage optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnum optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR ];
+ optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
+ optional protobuf_unittest_import.ImportEnum
+ default_import_enum = 83 [default = IMPORT_BAR];
+
+ optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+ optional string default_cord = 85 [ctype=CORD,default="123"];
+}
+
+message TestDeprecatedFields {
+ optional int32 deprecated_int32 = 1 [deprecated=true];
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+message TestAllExtensions {
+ extensions 1 to max;
+}
+
+extend TestAllExtensions {
+ // Singular
+ optional int32 optional_int32_extension = 1;
+ optional int64 optional_int64_extension = 2;
+ optional uint32 optional_uint32_extension = 3;
+ optional uint64 optional_uint64_extension = 4;
+ optional sint32 optional_sint32_extension = 5;
+ optional sint64 optional_sint64_extension = 6;
+ optional fixed32 optional_fixed32_extension = 7;
+ optional fixed64 optional_fixed64_extension = 8;
+ optional sfixed32 optional_sfixed32_extension = 9;
+ optional sfixed64 optional_sfixed64_extension = 10;
+ optional float optional_float_extension = 11;
+ optional double optional_double_extension = 12;
+ optional bool optional_bool_extension = 13;
+ optional string optional_string_extension = 14;
+ optional bytes optional_bytes_extension = 15;
+
+ optional group OptionalGroup_extension = 16 {
+ optional int32 a = 17;
+ }
+
+ optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
+ optional ForeignMessage optional_foreign_message_extension = 19;
+ optional protobuf_unittest_import.ImportMessage
+ optional_import_message_extension = 20;
+
+ optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
+ optional ForeignEnum optional_foreign_enum_extension = 22;
+ optional protobuf_unittest_import.ImportEnum
+ optional_import_enum_extension = 23;
+
+ optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
+ optional string optional_cord_extension = 25 [ctype=CORD];
+
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message_extension = 26;
+
+ optional TestAllTypes.NestedMessage
+ optional_lazy_message_extension = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32_extension = 31;
+ repeated int64 repeated_int64_extension = 32;
+ repeated uint32 repeated_uint32_extension = 33;
+ repeated uint64 repeated_uint64_extension = 34;
+ repeated sint32 repeated_sint32_extension = 35;
+ repeated sint64 repeated_sint64_extension = 36;
+ repeated fixed32 repeated_fixed32_extension = 37;
+ repeated fixed64 repeated_fixed64_extension = 38;
+ repeated sfixed32 repeated_sfixed32_extension = 39;
+ repeated sfixed64 repeated_sfixed64_extension = 40;
+ repeated float repeated_float_extension = 41;
+ repeated double repeated_double_extension = 42;
+ repeated bool repeated_bool_extension = 43;
+ repeated string repeated_string_extension = 44;
+ repeated bytes repeated_bytes_extension = 45;
+
+ repeated group RepeatedGroup_extension = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
+ repeated ForeignMessage repeated_foreign_message_extension = 49;
+ repeated protobuf_unittest_import.ImportMessage
+ repeated_import_message_extension = 50;
+
+ repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+ repeated ForeignEnum repeated_foreign_enum_extension = 52;
+ repeated protobuf_unittest_import.ImportEnum
+ repeated_import_enum_extension = 53;
+
+ repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord_extension = 55 [ctype=CORD];
+
+ repeated TestAllTypes.NestedMessage
+ repeated_lazy_message_extension = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32_extension = 61 [default = 41 ];
+ optional int64 default_int64_extension = 62 [default = 42 ];
+ optional uint32 default_uint32_extension = 63 [default = 43 ];
+ optional uint64 default_uint64_extension = 64 [default = 44 ];
+ optional sint32 default_sint32_extension = 65 [default = -45 ];
+ optional sint64 default_sint64_extension = 66 [default = 46 ];
+ optional fixed32 default_fixed32_extension = 67 [default = 47 ];
+ optional fixed64 default_fixed64_extension = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32_extension = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64_extension = 70 [default = -50 ];
+ optional float default_float_extension = 71 [default = 51.5 ];
+ optional double default_double_extension = 72 [default = 52e3 ];
+ optional bool default_bool_extension = 73 [default = true ];
+ optional string default_string_extension = 74 [default = "hello"];
+ optional bytes default_bytes_extension = 75 [default = "world"];
+
+ optional TestAllTypes.NestedEnum
+ default_nested_enum_extension = 81 [default = BAR];
+ optional ForeignEnum
+ default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
+ optional protobuf_unittest_import.ImportEnum
+ default_import_enum_extension = 83 [default = IMPORT_BAR];
+
+ optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
+ default="abc"];
+ optional string default_cord_extension = 85 [ctype=CORD, default="123"];
+}
+
+message TestNestedExtension {
+ extend TestAllExtensions {
+ // Check for bug where string extensions declared in tested scope did not
+ // compile.
+ optional string test = 1002 [default="test"];
+ }
+}
+
+// We have separate messages for testing required fields because it's
+// annoying to have to fill in required fields in TestProto in order to
+// do anything with it. Note that we don't need to test every type of
+// required filed because the code output is basically identical to
+// optional fields for all types.
+message TestRequired {
+ required int32 a = 1;
+ optional int32 dummy2 = 2;
+ required int32 b = 3;
+
+ extend TestAllExtensions {
+ optional TestRequired single = 1000;
+ repeated TestRequired multi = 1001;
+ }
+
+ // Pad the field count to 32 so that we can test that IsInitialized()
+ // properly checks multiple elements of has_bits_.
+ optional int32 dummy4 = 4;
+ optional int32 dummy5 = 5;
+ optional int32 dummy6 = 6;
+ optional int32 dummy7 = 7;
+ optional int32 dummy8 = 8;
+ optional int32 dummy9 = 9;
+ optional int32 dummy10 = 10;
+ optional int32 dummy11 = 11;
+ optional int32 dummy12 = 12;
+ optional int32 dummy13 = 13;
+ optional int32 dummy14 = 14;
+ optional int32 dummy15 = 15;
+ optional int32 dummy16 = 16;
+ optional int32 dummy17 = 17;
+ optional int32 dummy18 = 18;
+ optional int32 dummy19 = 19;
+ optional int32 dummy20 = 20;
+ optional int32 dummy21 = 21;
+ optional int32 dummy22 = 22;
+ optional int32 dummy23 = 23;
+ optional int32 dummy24 = 24;
+ optional int32 dummy25 = 25;
+ optional int32 dummy26 = 26;
+ optional int32 dummy27 = 27;
+ optional int32 dummy28 = 28;
+ optional int32 dummy29 = 29;
+ optional int32 dummy30 = 30;
+ optional int32 dummy31 = 31;
+ optional int32 dummy32 = 32;
+
+ required int32 c = 33;
+}
+
+message TestRequiredForeign {
+ optional TestRequired optional_message = 1;
+ repeated TestRequired repeated_message = 2;
+ optional int32 dummy = 3;
+}
+
+// Test that we can use NestedMessage from outside TestAllTypes.
+message TestForeignNested {
+ optional TestAllTypes.NestedMessage foreign_nested = 1;
+}
+
+// TestEmptyMessage is used to test unknown field support.
+message TestEmptyMessage {
+}
+
+// Like above, but declare all field numbers as potential extensions. No
+// actual extensions should ever be defined for this type.
+message TestEmptyMessageWithExtensions {
+ extensions 1 to max;
+}
+
+message TestMultipleExtensionRanges {
+ extensions 42;
+ extensions 4143 to 4243;
+ extensions 65536 to max;
+}
+
+// Test that really large tag numbers don't break anything.
+message TestReallyLargeTagNumber {
+ // The largest possible tag number is 2^28 - 1, since the wire format uses
+ // three bits to communicate wire type.
+ optional int32 a = 1;
+ optional int32 bb = 268435455;
+}
+
+message TestRecursiveMessage {
+ optional TestRecursiveMessage a = 1;
+ optional int32 i = 2;
+}
+
+// Test that mutual recursion works.
+message TestMutualRecursionA {
+ optional TestMutualRecursionB bb = 1;
+}
+
+message TestMutualRecursionB {
+ optional TestMutualRecursionA a = 1;
+ optional int32 optional_int32 = 2;
+}
+
+// Test that groups have disjoint field numbers from their siblings and
+// parents. This is NOT possible in proto1; only proto2. When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in protobuf_unittest_proto.
+message TestDupFieldNumber { // NO_PROTO1
+ optional int32 a = 1; // NO_PROTO1
+ optional group Foo = 2 { optional int32 a = 1; } // NO_PROTO1
+ optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1
+} // NO_PROTO1
+
+// Additional messages for testing lazy fields.
+message TestEagerMessage {
+ optional TestAllTypes sub_message = 1 [lazy=false];
+}
+message TestLazyMessage {
+ optional TestAllTypes sub_message = 1 [lazy=true];
+}
+
+// Needed for a Python test.
+message TestNestedMessageHasBits {
+ message NestedMessage {
+ repeated int32 nestedmessage_repeated_int32 = 1;
+ repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
+ }
+ optional NestedMessage optional_nested_message = 1;
+}
+
+
+// Test an enum that has multiple values with the same number.
+enum TestEnumWithDupValue {
+ option allow_alias = true;
+ FOO1 = 1;
+ BAR1 = 2;
+ BAZ = 3;
+ FOO2 = 1;
+ BAR2 = 2;
+}
+
+// Test an enum with large, unordered values.
+enum TestSparseEnum {
+ SPARSE_A = 123;
+ SPARSE_B = 62374;
+ SPARSE_C = 12589234;
+ SPARSE_D = -15;
+ SPARSE_E = -53452;
+ SPARSE_F = 0;
+ SPARSE_G = 2;
+}
+
+// Test message with CamelCase field names. This violates Protocol Buffer
+// standard style.
+message TestCamelCaseFieldNames {
+ optional int32 PrimitiveField = 1;
+ optional string StringField = 2;
+ optional ForeignEnum EnumField = 3;
+ optional ForeignMessage MessageField = 4;
+ optional string StringPieceField = 5 [ctype=STRING_PIECE];
+ optional string CordField = 6 [ctype=CORD];
+
+ repeated int32 RepeatedPrimitiveField = 7;
+ repeated string RepeatedStringField = 8;
+ repeated ForeignEnum RepeatedEnumField = 9;
+ repeated ForeignMessage RepeatedMessageField = 10;
+ repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
+ repeated string RepeatedCordField = 12 [ctype=CORD];
+}
+
+
+// We list fields out of order, to ensure that we're using field number and not
+// field index to determine serialization order.
+message TestFieldOrderings {
+ optional string my_string = 11;
+ extensions 2 to 10;
+ optional int64 my_int = 1;
+ extensions 12 to 100;
+ optional float my_float = 101;
+}
+
+
+extend TestFieldOrderings {
+ optional string my_extension_string = 50;
+ optional int32 my_extension_int = 5;
+}
+
+
+message TestExtremeDefaultValues {
+ optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
+ optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
+ optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
+ optional int32 small_int32 = 4 [default = -0x7FFFFFFF];
+ optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF];
+ optional int32 really_small_int32 = 21 [default = -0x80000000];
+ optional int64 really_small_int64 = 22 [default = -0x8000000000000000];
+
+ // The default value here is UTF-8 for "\u1234". (We could also just type
+ // the UTF-8 text directly into this text file rather than escape it, but
+ // lots of people use editors that would be confused by this.)
+ optional string utf8_string = 6 [default = "\341\210\264"];
+
+ // Tests for single-precision floating-point values.
+ optional float zero_float = 7 [default = 0];
+ optional float one_float = 8 [default = 1];
+ optional float small_float = 9 [default = 1.5];
+ optional float negative_one_float = 10 [default = -1];
+ optional float negative_float = 11 [default = -1.5];
+ // Using exponents
+ optional float large_float = 12 [default = 2E8];
+ optional float small_negative_float = 13 [default = -8e-28];
+
+ // Text for nonfinite floating-point values.
+ optional double inf_double = 14 [default = inf];
+ optional double neg_inf_double = 15 [default = -inf];
+ optional double nan_double = 16 [default = nan];
+ optional float inf_float = 17 [default = inf];
+ optional float neg_inf_float = 18 [default = -inf];
+ optional float nan_float = 19 [default = nan];
+
+ // Tests for C++ trigraphs.
+ // Trigraphs should be escaped in C++ generated files, but they should not be
+ // escaped for other languages.
+ // Note that in .proto file, "\?" is a valid way to escape ? in string
+ // literals.
+ optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
+
+ // String defaults containing the character '\000'
+ optional string string_with_zero = 23 [default = "hel\000lo"];
+ optional bytes bytes_with_zero = 24 [default = "wor\000ld"];
+ optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
+ default="ab\000c"];
+ optional string cord_with_zero = 26 [ctype=CORD,
+ default="12\0003"];
+}
+
+message SparseEnumMessage {
+ optional TestSparseEnum sparse_enum = 1;
+}
+
+// Test String and Bytes: string is for valid UTF-8 strings
+message OneString {
+ optional string data = 1;
+}
+
+message MoreString {
+ repeated string data = 1;
+}
+
+message OneBytes {
+ optional bytes data = 1;
+}
+
+message MoreBytes {
+ repeated bytes data = 1;
+}
+
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+ repeated int32 unpacked_int32 = 90 [packed = false];
+ repeated int64 unpacked_int64 = 91 [packed = false];
+ repeated uint32 unpacked_uint32 = 92 [packed = false];
+ repeated uint64 unpacked_uint64 = 93 [packed = false];
+ repeated sint32 unpacked_sint32 = 94 [packed = false];
+ repeated sint64 unpacked_sint64 = 95 [packed = false];
+ repeated fixed32 unpacked_fixed32 = 96 [packed = false];
+ repeated fixed64 unpacked_fixed64 = 97 [packed = false];
+ repeated sfixed32 unpacked_sfixed32 = 98 [packed = false];
+ repeated sfixed64 unpacked_sfixed64 = 99 [packed = false];
+ repeated float unpacked_float = 100 [packed = false];
+ repeated double unpacked_double = 101 [packed = false];
+ repeated bool unpacked_bool = 102 [packed = false];
+ repeated ForeignEnum unpacked_enum = 103 [packed = false];
+}
+
+message TestPackedExtensions {
+ extensions 1 to max;
+}
+
+extend TestPackedExtensions {
+ repeated int32 packed_int32_extension = 90 [packed = true];
+ repeated int64 packed_int64_extension = 91 [packed = true];
+ repeated uint32 packed_uint32_extension = 92 [packed = true];
+ repeated uint64 packed_uint64_extension = 93 [packed = true];
+ repeated sint32 packed_sint32_extension = 94 [packed = true];
+ repeated sint64 packed_sint64_extension = 95 [packed = true];
+ repeated fixed32 packed_fixed32_extension = 96 [packed = true];
+ repeated fixed64 packed_fixed64_extension = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32_extension = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64_extension = 99 [packed = true];
+ repeated float packed_float_extension = 100 [packed = true];
+ repeated double packed_double_extension = 101 [packed = true];
+ repeated bool packed_bool_extension = 102 [packed = true];
+ repeated ForeignEnum packed_enum_extension = 103 [packed = true];
+}
+
+// Used by ExtensionSetTest/DynamicExtensions. The test actually builds
+// a set of extensions to TestAllExtensions dynamically, based on the fields
+// of this message type.
+message TestDynamicExtensions {
+ enum DynamicEnumType {
+ DYNAMIC_FOO = 2200;
+ DYNAMIC_BAR = 2201;
+ DYNAMIC_BAZ = 2202;
+ }
+ message DynamicMessageType {
+ optional int32 dynamic_field = 2100;
+ }
+
+ optional fixed32 scalar_extension = 2000;
+ optional ForeignEnum enum_extension = 2001;
+ optional DynamicEnumType dynamic_enum_extension = 2002;
+
+ optional ForeignMessage message_extension = 2003;
+ optional DynamicMessageType dynamic_message_extension = 2004;
+
+ repeated string repeated_extension = 2005;
+ repeated sint32 packed_extension = 2006 [packed = true];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+ // Parsing repeated fixed size values used to fail. This message needs to be
+ // used in order to get a tag of the right size; all of the repeated fields
+ // in TestAllTypes didn't trigger the check.
+ repeated fixed32 repeated_fixed32 = 12;
+ // Check for a varint type, just for good measure.
+ repeated int32 repeated_int32 = 13;
+
+ // These have two-byte tags.
+ repeated fixed64 repeated_fixed64 = 2046;
+ repeated int64 repeated_int64 = 2047;
+
+ // Three byte tags.
+ repeated float repeated_float = 262142;
+ repeated uint64 repeated_uint64 = 262143;
+}
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+message TestParsingMerge {
+ // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
+ // except that all fields are repeated. In the tests, we will serialize the
+ // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
+ // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
+ // the corresponding required/optional fields in TestParsingMerge.
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypes field1 = 1;
+ repeated TestAllTypes field2 = 2;
+ repeated TestAllTypes field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypes field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypes field1 = 21;
+ }
+ repeated TestAllTypes ext1 = 1000;
+ repeated TestAllTypes ext2 = 1001;
+ }
+ required TestAllTypes required_all_types = 1;
+ optional TestAllTypes optional_all_types = 2;
+ repeated TestAllTypes repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypes optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypes repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMerge {
+ optional TestAllTypes optional_ext = 1000;
+ repeated TestAllTypes repeated_ext = 1001;
+ }
+}
+
+message TestCommentInjectionMessage {
+ // */ <- This should not close the generated doc comment
+ optional string a = 1 [default="*/ <- Neither should this."];
+}
+
+
+// Test that RPC services work.
+message FooRequest {}
+message FooResponse {}
+
+message FooClientMessage {}
+message FooServerMessage{}
+
+service TestService {
+ rpc Foo(FooRequest) returns (FooResponse);
+ rpc Bar(BarRequest) returns (BarResponse);
+}
+
+
+message BarRequest {}
+message BarResponse {}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto
new file mode 100644
index 0000000000..e591d29447
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_custom_options.proto
@@ -0,0 +1,387 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: benjy@google.com (Benjy Weinberger)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file used to test the "custom options" feature of proto2.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true;
+
+// A custom file option (defined below).
+option (file_opt1) = 9876543210;
+
+import "google/protobuf/descriptor.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+package protobuf_unittest;
+
+
+// Some simple test custom options of various types.
+
+extend google.protobuf.FileOptions {
+ optional uint64 file_opt1 = 7736974;
+}
+
+extend google.protobuf.MessageOptions {
+ optional int32 message_opt1 = 7739036;
+}
+
+extend google.protobuf.FieldOptions {
+ optional fixed64 field_opt1 = 7740936;
+ // This is useful for testing that we correctly register default values for
+ // extension options.
+ optional int32 field_opt2 = 7753913 [default=42];
+}
+
+extend google.protobuf.EnumOptions {
+ optional sfixed32 enum_opt1 = 7753576;
+}
+
+extend google.protobuf.EnumValueOptions {
+ optional int32 enum_value_opt1 = 1560678;
+}
+
+extend google.protobuf.ServiceOptions {
+ optional sint64 service_opt1 = 7887650;
+}
+
+enum MethodOpt1 {
+ METHODOPT1_VAL1 = 1;
+ METHODOPT1_VAL2 = 2;
+}
+
+extend google.protobuf.MethodOptions {
+ optional MethodOpt1 method_opt1 = 7890860;
+}
+
+// A test message with custom options at all possible locations (and also some
+// regular options, to make sure they interact nicely).
+message TestMessageWithCustomOptions {
+ option message_set_wire_format = false;
+
+ option (message_opt1) = -56;
+
+ optional string field1 = 1 [ctype=CORD,
+ (field_opt1)=8765432109];
+
+ enum AnEnum {
+ option (enum_opt1) = -789;
+
+ ANENUM_VAL1 = 1;
+ ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
+ }
+}
+
+
+// A test RPC service with custom options at all possible locations (and also
+// some regular options, to make sure they interact nicely).
+message CustomOptionFooRequest {
+}
+
+message CustomOptionFooResponse {
+}
+
+message CustomOptionFooClientMessage {
+}
+
+message CustomOptionFooServerMessage {
+}
+
+service TestServiceWithCustomOptions {
+ option (service_opt1) = -9876543210;
+
+ rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
+ option (method_opt1) = METHODOPT1_VAL2;
+ }
+}
+
+
+
+// Options of every possible field type, so we can test them all exhaustively.
+
+message DummyMessageContainingEnum {
+ enum TestEnumType {
+ TEST_OPTION_ENUM_TYPE1 = 22;
+ TEST_OPTION_ENUM_TYPE2 = -23;
+ }
+}
+
+message DummyMessageInvalidAsOptionType {
+}
+
+extend google.protobuf.MessageOptions {
+ optional bool bool_opt = 7706090;
+ optional int32 int32_opt = 7705709;
+ optional int64 int64_opt = 7705542;
+ optional uint32 uint32_opt = 7704880;
+ optional uint64 uint64_opt = 7702367;
+ optional sint32 sint32_opt = 7701568;
+ optional sint64 sint64_opt = 7700863;
+ optional fixed32 fixed32_opt = 7700307;
+ optional fixed64 fixed64_opt = 7700194;
+ optional sfixed32 sfixed32_opt = 7698645;
+ optional sfixed64 sfixed64_opt = 7685475;
+ optional float float_opt = 7675390;
+ optional double double_opt = 7673293;
+ optional string string_opt = 7673285;
+ optional bytes bytes_opt = 7673238;
+ optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
+ optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
+}
+
+message CustomOptionMinIntegerValues {
+ option (bool_opt) = false;
+ option (int32_opt) = -0x80000000;
+ option (int64_opt) = -0x8000000000000000;
+ option (uint32_opt) = 0;
+ option (uint64_opt) = 0;
+ option (sint32_opt) = -0x80000000;
+ option (sint64_opt) = -0x8000000000000000;
+ option (fixed32_opt) = 0;
+ option (fixed64_opt) = 0;
+ option (sfixed32_opt) = -0x80000000;
+ option (sfixed64_opt) = -0x8000000000000000;
+}
+
+message CustomOptionMaxIntegerValues {
+ option (bool_opt) = true;
+ option (int32_opt) = 0x7FFFFFFF;
+ option (int64_opt) = 0x7FFFFFFFFFFFFFFF;
+ option (uint32_opt) = 0xFFFFFFFF;
+ option (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
+ option (sint32_opt) = 0x7FFFFFFF;
+ option (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
+ option (fixed32_opt) = 0xFFFFFFFF;
+ option (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
+ option (sfixed32_opt) = 0x7FFFFFFF;
+ option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
+}
+
+message CustomOptionOtherValues {
+ option (int32_opt) = -100; // To test sign-extension.
+ option (float_opt) = 12.3456789;
+ option (double_opt) = 1.234567890123456789;
+ option (string_opt) = "Hello, \"World\"";
+ option (bytes_opt) = "Hello\0World";
+ option (enum_opt) = TEST_OPTION_ENUM_TYPE2;
+}
+
+message SettingRealsFromPositiveInts {
+ option (float_opt) = 12;
+ option (double_opt) = 154;
+}
+
+message SettingRealsFromNegativeInts {
+ option (float_opt) = -12;
+ option (double_opt) = -154;
+}
+
+// Options of complex message types, themselves combined and extended in
+// various ways.
+
+message ComplexOptionType1 {
+ optional int32 foo = 1;
+ optional int32 foo2 = 2;
+ optional int32 foo3 = 3;
+
+ extensions 100 to max;
+}
+
+message ComplexOptionType2 {
+ optional ComplexOptionType1 bar = 1;
+ optional int32 baz = 2;
+
+ message ComplexOptionType4 {
+ optional int32 waldo = 1;
+
+ extend google.protobuf.MessageOptions {
+ optional ComplexOptionType4 complex_opt4 = 7633546;
+ }
+ }
+
+ optional ComplexOptionType4 fred = 3;
+
+ extensions 100 to max;
+}
+
+message ComplexOptionType3 {
+ optional int32 qux = 1;
+
+ optional group ComplexOptionType5 = 2 {
+ optional int32 plugh = 3;
+ }
+}
+
+extend ComplexOptionType1 {
+ optional int32 quux = 7663707;
+ optional ComplexOptionType3 corge = 7663442;
+}
+
+extend ComplexOptionType2 {
+ optional int32 grault = 7650927;
+ optional ComplexOptionType1 garply = 7649992;
+}
+
+extend google.protobuf.MessageOptions {
+ optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
+ optional ComplexOptionType2 complex_opt2 = 7636949;
+ optional ComplexOptionType3 complex_opt3 = 7636463;
+ optional group ComplexOpt6 = 7595468 {
+ optional int32 xyzzy = 7593951;
+ }
+}
+
+// Note that we try various different ways of naming the same extension.
+message VariousComplexOptions {
+ option (.protobuf_unittest.complex_opt1).foo = 42;
+ option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
+ option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
+ option (complex_opt2).baz = 987;
+ option (complex_opt2).(grault) = 654;
+ option (complex_opt2).bar.foo = 743;
+ option (complex_opt2).bar.(quux) = 1999;
+ option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
+ option (complex_opt2).(garply).foo = 741;
+ option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
+ option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
+ option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
+ option (complex_opt2).fred.waldo = 321;
+ option (protobuf_unittest.complex_opt3).qux = 9;
+ option (complex_opt3).complexoptiontype5.plugh = 22;
+ option (complexopt6).xyzzy = 24;
+}
+
+// ------------------------------------------------------
+// Definitions for testing aggregate option parsing.
+// See descriptor_unittest.cc.
+
+message AggregateMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message AggregateMessageSetElement {
+ extend AggregateMessageSet {
+ optional AggregateMessageSetElement message_set_extension = 15447542;
+ }
+ optional string s = 1;
+}
+
+// A helper type used to test aggregate option parsing
+message Aggregate {
+ optional int32 i = 1;
+ optional string s = 2;
+
+ // A nested object
+ optional Aggregate sub = 3;
+
+ // To test the parsing of extensions inside aggregate values
+ optional google.protobuf.FileOptions file = 4;
+ extend google.protobuf.FileOptions {
+ optional Aggregate nested = 15476903;
+ }
+
+ // An embedded message set
+ optional AggregateMessageSet mset = 5;
+}
+
+// Allow Aggregate to be used as an option at all possible locations
+// in the .proto grammer.
+extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; }
+extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; }
+extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; }
+extend google.protobuf.EnumOptions { optional Aggregate enumopt = 15483218; }
+extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
+extend google.protobuf.ServiceOptions { optional Aggregate serviceopt = 15497145; }
+extend google.protobuf.MethodOptions { optional Aggregate methodopt = 15512713; }
+
+// Try using AggregateOption at different points in the proto grammar
+option (fileopt) = {
+ s: 'FileAnnotation'
+ // Also test the handling of comments
+ /* of both types */ i: 100
+
+ sub { s: 'NestedFileAnnotation' }
+
+ // Include a google.protobuf.FileOptions and recursively extend it with
+ // another fileopt.
+ file {
+ [protobuf_unittest.fileopt] {
+ s:'FileExtensionAnnotation'
+ }
+ }
+
+ // A message set inside an option value
+ mset {
+ [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
+ s: 'EmbeddedMessageSetElement'
+ }
+ }
+};
+
+message AggregateMessage {
+ option (msgopt) = { i:101 s:'MessageAnnotation' };
+ optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
+}
+
+service AggregateService {
+ option (serviceopt) = { s:'ServiceAnnotation' };
+ rpc Method (AggregateMessage) returns (AggregateMessage) {
+ option (methodopt) = { s:'MethodAnnotation' };
+ }
+}
+
+enum AggregateEnum {
+ option (enumopt) = { s:'EnumAnnotation' };
+ VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
+}
+
+// Test custom options for nested type.
+message NestedOptionType {
+ message NestedMessage {
+ option (message_opt1) = 1001;
+ optional int32 nested_field = 1 [(field_opt1) = 1002];
+ }
+ enum NestedEnum {
+ option (enum_opt1) = 1003;
+ NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
+ }
+ extend google.protobuf.FileOptions {
+ optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
new file mode 100644
index 0000000000..fa1762594e
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
+
+import "google/protobuf/unittest_optimize_for.proto";
+
+package protobuf_unittest;
+
+// We optimize for speed here, but we are importing a proto that is optimized
+// for code size.
+option optimize_for = SPEED;
+
+message TestEmbedOptimizedForSize {
+ // Test that embedding a message which has optimize_for = CODE_SIZE into
+ // one optimized for speed works.
+ optional TestOptimizedForSize optional_message = 1;
+ repeated TestOptimizedForSize repeated_message = 2;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto
new file mode 100644
index 0000000000..ab12d1fb9f
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_empty.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file intentionally left blank. (At one point this wouldn't compile
+// correctly.)
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
new file mode 100644
index 0000000000..bc0b7c16a0
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
@@ -0,0 +1,1046 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file that has an extremely large descriptor. Used to test that
+// descriptors over 64k don't break the string literal length limit in Java.
+
+
+package google.protobuf;
+option java_package = "com.google.protobuf";
+
+// Avoid generating insanely long methods.
+option optimize_for = CODE_SIZE;
+
+message TestEnormousDescriptor {
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1 = 1 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_2 = 2 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_3 = 3 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_4 = 4 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_5 = 5 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_6 = 6 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_7 = 7 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_8 = 8 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_9 = 9 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_10 = 10 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_11 = 11 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_12 = 12 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_13 = 13 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_14 = 14 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_15 = 15 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_16 = 16 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_17 = 17 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_18 = 18 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_19 = 19 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_20 = 20 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_21 = 21 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_22 = 22 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_23 = 23 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_24 = 24 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_25 = 25 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_26 = 26 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_27 = 27 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_28 = 28 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_29 = 29 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_30 = 30 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_31 = 31 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_32 = 32 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_33 = 33 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_34 = 34 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_35 = 35 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_36 = 36 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_37 = 37 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_38 = 38 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_39 = 39 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_40 = 40 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_41 = 41 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_42 = 42 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_43 = 43 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_44 = 44 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_45 = 45 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_46 = 46 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_47 = 47 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_48 = 48 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_49 = 49 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_50 = 50 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_51 = 51 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_52 = 52 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_53 = 53 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_54 = 54 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_55 = 55 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_56 = 56 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_57 = 57 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_58 = 58 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_59 = 59 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_60 = 60 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_61 = 61 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_62 = 62 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_63 = 63 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_64 = 64 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_65 = 65 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_66 = 66 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_67 = 67 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_68 = 68 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_69 = 69 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_70 = 70 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_71 = 71 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_72 = 72 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_73 = 73 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_74 = 74 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_75 = 75 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_76 = 76 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_77 = 77 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_78 = 78 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_79 = 79 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_80 = 80 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_81 = 81 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_82 = 82 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_83 = 83 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_84 = 84 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_85 = 85 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_86 = 86 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_87 = 87 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_88 = 88 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_89 = 89 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_90 = 90 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_91 = 91 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_92 = 92 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_93 = 93 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_94 = 94 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_95 = 95 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_96 = 96 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_97 = 97 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_98 = 98 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_99 = 99 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_100 = 100 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_101 = 101 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_102 = 102 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_103 = 103 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_104 = 104 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_105 = 105 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_106 = 106 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_107 = 107 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_108 = 108 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_109 = 109 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_110 = 110 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_111 = 111 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_112 = 112 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_113 = 113 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_114 = 114 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_115 = 115 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_116 = 116 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_117 = 117 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_118 = 118 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_119 = 119 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_120 = 120 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_121 = 121 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_122 = 122 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_123 = 123 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_124 = 124 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_125 = 125 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_126 = 126 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_127 = 127 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_128 = 128 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_129 = 129 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_130 = 130 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_131 = 131 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_132 = 132 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_133 = 133 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_134 = 134 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_135 = 135 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_136 = 136 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_137 = 137 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_138 = 138 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_139 = 139 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_140 = 140 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_141 = 141 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_142 = 142 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_143 = 143 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_144 = 144 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_145 = 145 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_146 = 146 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_147 = 147 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_148 = 148 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_149 = 149 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_150 = 150 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_151 = 151 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_152 = 152 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_153 = 153 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_154 = 154 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_155 = 155 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_156 = 156 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_157 = 157 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_158 = 158 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_159 = 159 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_160 = 160 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_161 = 161 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_162 = 162 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_163 = 163 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_164 = 164 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_165 = 165 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_166 = 166 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_167 = 167 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_168 = 168 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_169 = 169 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_170 = 170 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_171 = 171 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_172 = 172 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_173 = 173 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_174 = 174 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_175 = 175 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_176 = 176 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_177 = 177 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_178 = 178 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_179 = 179 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_180 = 180 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_181 = 181 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_182 = 182 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_183 = 183 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_184 = 184 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_185 = 185 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_186 = 186 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_187 = 187 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_188 = 188 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_189 = 189 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_190 = 190 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_191 = 191 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_192 = 192 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_193 = 193 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_194 = 194 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_195 = 195 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_196 = 196 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_197 = 197 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_198 = 198 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_199 = 199 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_200 = 200 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_201 = 201 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_202 = 202 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_203 = 203 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_204 = 204 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_205 = 205 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_206 = 206 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_207 = 207 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_208 = 208 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_209 = 209 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_210 = 210 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_211 = 211 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_212 = 212 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_213 = 213 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_214 = 214 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_215 = 215 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_216 = 216 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_217 = 217 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_218 = 218 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_219 = 219 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_220 = 220 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_221 = 221 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_222 = 222 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_223 = 223 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_224 = 224 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_225 = 225 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_226 = 226 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_227 = 227 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_228 = 228 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_229 = 229 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_230 = 230 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_231 = 231 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_232 = 232 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_233 = 233 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_234 = 234 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_235 = 235 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_236 = 236 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_237 = 237 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_238 = 238 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_239 = 239 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_240 = 240 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_241 = 241 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_242 = 242 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_243 = 243 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_244 = 244 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_245 = 245 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_246 = 246 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_247 = 247 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_248 = 248 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_249 = 249 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_250 = 250 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_251 = 251 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_252 = 252 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_253 = 253 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_254 = 254 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_255 = 255 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_256 = 256 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_257 = 257 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_258 = 258 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_259 = 259 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_260 = 260 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_261 = 261 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_262 = 262 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_263 = 263 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_264 = 264 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_265 = 265 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_266 = 266 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_267 = 267 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_268 = 268 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_269 = 269 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_270 = 270 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_271 = 271 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_272 = 272 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_273 = 273 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_274 = 274 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_275 = 275 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_276 = 276 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_277 = 277 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_278 = 278 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_279 = 279 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_280 = 280 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_281 = 281 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_282 = 282 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_283 = 283 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_284 = 284 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_285 = 285 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_286 = 286 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_287 = 287 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_288 = 288 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_289 = 289 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_290 = 290 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_291 = 291 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_292 = 292 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_293 = 293 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_294 = 294 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_295 = 295 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_296 = 296 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_297 = 297 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_298 = 298 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_299 = 299 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_300 = 300 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_301 = 301 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_302 = 302 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_303 = 303 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_304 = 304 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_305 = 305 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_306 = 306 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_307 = 307 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_308 = 308 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_309 = 309 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_310 = 310 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_311 = 311 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_312 = 312 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_313 = 313 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_314 = 314 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_315 = 315 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_316 = 316 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_317 = 317 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_318 = 318 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_319 = 319 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_320 = 320 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_321 = 321 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_322 = 322 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_323 = 323 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_324 = 324 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_325 = 325 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_326 = 326 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_327 = 327 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_328 = 328 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_329 = 329 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_330 = 330 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_331 = 331 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_332 = 332 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_333 = 333 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_334 = 334 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_335 = 335 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_336 = 336 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_337 = 337 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_338 = 338 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_339 = 339 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_340 = 340 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_341 = 341 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_342 = 342 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_343 = 343 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_344 = 344 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_345 = 345 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_346 = 346 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_347 = 347 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_348 = 348 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_349 = 349 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_350 = 350 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_351 = 351 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_352 = 352 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_353 = 353 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_354 = 354 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_355 = 355 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_356 = 356 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_357 = 357 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_358 = 358 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_359 = 359 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_360 = 360 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_361 = 361 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_362 = 362 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_363 = 363 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_364 = 364 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_365 = 365 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_366 = 366 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_367 = 367 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_368 = 368 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_369 = 369 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_370 = 370 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_371 = 371 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_372 = 372 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_373 = 373 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_374 = 374 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_375 = 375 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_376 = 376 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_377 = 377 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_378 = 378 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_379 = 379 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_380 = 380 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_381 = 381 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_382 = 382 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_383 = 383 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_384 = 384 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_385 = 385 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_386 = 386 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_387 = 387 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_388 = 388 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_389 = 389 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_390 = 390 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_391 = 391 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_392 = 392 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_393 = 393 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_394 = 394 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_395 = 395 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_396 = 396 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_397 = 397 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_398 = 398 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_399 = 399 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_400 = 400 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_401 = 401 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_402 = 402 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_403 = 403 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_404 = 404 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_405 = 405 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_406 = 406 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_407 = 407 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_408 = 408 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_409 = 409 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_410 = 410 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_411 = 411 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_412 = 412 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_413 = 413 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_414 = 414 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_415 = 415 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_416 = 416 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_417 = 417 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_418 = 418 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_419 = 419 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_420 = 420 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_421 = 421 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_422 = 422 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_423 = 423 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_424 = 424 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_425 = 425 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_426 = 426 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_427 = 427 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_428 = 428 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_429 = 429 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_430 = 430 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_431 = 431 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_432 = 432 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_433 = 433 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_434 = 434 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_435 = 435 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_436 = 436 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_437 = 437 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_438 = 438 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_439 = 439 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_440 = 440 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_441 = 441 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_442 = 442 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_443 = 443 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_444 = 444 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_445 = 445 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_446 = 446 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_447 = 447 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_448 = 448 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_449 = 449 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_450 = 450 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_451 = 451 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_452 = 452 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_453 = 453 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_454 = 454 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_455 = 455 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_456 = 456 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_457 = 457 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_458 = 458 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_459 = 459 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_460 = 460 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_461 = 461 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_462 = 462 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_463 = 463 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_464 = 464 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_465 = 465 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_466 = 466 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_467 = 467 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_468 = 468 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_469 = 469 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_470 = 470 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_471 = 471 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_472 = 472 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_473 = 473 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_474 = 474 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_475 = 475 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_476 = 476 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_477 = 477 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_478 = 478 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_479 = 479 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_480 = 480 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_481 = 481 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_482 = 482 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_483 = 483 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_484 = 484 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_485 = 485 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_486 = 486 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_487 = 487 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_488 = 488 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_489 = 489 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_490 = 490 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_491 = 491 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_492 = 492 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_493 = 493 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_494 = 494 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_495 = 495 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_496 = 496 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_497 = 497 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_498 = 498 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_499 = 499 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_500 = 500 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_501 = 501 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_502 = 502 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_503 = 503 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_504 = 504 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_505 = 505 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_506 = 506 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_507 = 507 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_508 = 508 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_509 = 509 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_510 = 510 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_511 = 511 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_512 = 512 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_513 = 513 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_514 = 514 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_515 = 515 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_516 = 516 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_517 = 517 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_518 = 518 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_519 = 519 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_520 = 520 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_521 = 521 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_522 = 522 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_523 = 523 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_524 = 524 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_525 = 525 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_526 = 526 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_527 = 527 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_528 = 528 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_529 = 529 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_530 = 530 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_531 = 531 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_532 = 532 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_533 = 533 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_534 = 534 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_535 = 535 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_536 = 536 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_537 = 537 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_538 = 538 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_539 = 539 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_540 = 540 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_541 = 541 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_542 = 542 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_543 = 543 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_544 = 544 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_545 = 545 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_546 = 546 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_547 = 547 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_548 = 548 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_549 = 549 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_550 = 550 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_551 = 551 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_552 = 552 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_553 = 553 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_554 = 554 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_555 = 555 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_556 = 556 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_557 = 557 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_558 = 558 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_559 = 559 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_560 = 560 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_561 = 561 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_562 = 562 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_563 = 563 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_564 = 564 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_565 = 565 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_566 = 566 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_567 = 567 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_568 = 568 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_569 = 569 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_570 = 570 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_571 = 571 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_572 = 572 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_573 = 573 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_574 = 574 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_575 = 575 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_576 = 576 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_577 = 577 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_578 = 578 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_579 = 579 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_580 = 580 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_581 = 581 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_582 = 582 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_583 = 583 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_584 = 584 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_585 = 585 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_586 = 586 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_587 = 587 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_588 = 588 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_589 = 589 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_590 = 590 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_591 = 591 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_592 = 592 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_593 = 593 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_594 = 594 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_595 = 595 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_596 = 596 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_597 = 597 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_598 = 598 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_599 = 599 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_600 = 600 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_601 = 601 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_602 = 602 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_603 = 603 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_604 = 604 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_605 = 605 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_606 = 606 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_607 = 607 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_608 = 608 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_609 = 609 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_610 = 610 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_611 = 611 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_612 = 612 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_613 = 613 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_614 = 614 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_615 = 615 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_616 = 616 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_617 = 617 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_618 = 618 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_619 = 619 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_620 = 620 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_621 = 621 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_622 = 622 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_623 = 623 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_624 = 624 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_625 = 625 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_626 = 626 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_627 = 627 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_628 = 628 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_629 = 629 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_630 = 630 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_631 = 631 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_632 = 632 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_633 = 633 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_634 = 634 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_635 = 635 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_636 = 636 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_637 = 637 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_638 = 638 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_639 = 639 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_640 = 640 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_641 = 641 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_642 = 642 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_643 = 643 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_644 = 644 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_645 = 645 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_646 = 646 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_647 = 647 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_648 = 648 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_649 = 649 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_650 = 650 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_651 = 651 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_652 = 652 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_653 = 653 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_654 = 654 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_655 = 655 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_656 = 656 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_657 = 657 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_658 = 658 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_659 = 659 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_660 = 660 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_661 = 661 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_662 = 662 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_663 = 663 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_664 = 664 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_665 = 665 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_666 = 666 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_667 = 667 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_668 = 668 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_669 = 669 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_670 = 670 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_671 = 671 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_672 = 672 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_673 = 673 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_674 = 674 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_675 = 675 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_676 = 676 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_677 = 677 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_678 = 678 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_679 = 679 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_680 = 680 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_681 = 681 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_682 = 682 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_683 = 683 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_684 = 684 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_685 = 685 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_686 = 686 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_687 = 687 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_688 = 688 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_689 = 689 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_690 = 690 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_691 = 691 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_692 = 692 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_693 = 693 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_694 = 694 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_695 = 695 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_696 = 696 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_697 = 697 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_698 = 698 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_699 = 699 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_700 = 700 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_701 = 701 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_702 = 702 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_703 = 703 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_704 = 704 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_705 = 705 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_706 = 706 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_707 = 707 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_708 = 708 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_709 = 709 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_710 = 710 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_711 = 711 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_712 = 712 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_713 = 713 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_714 = 714 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_715 = 715 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_716 = 716 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_717 = 717 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_718 = 718 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_719 = 719 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_720 = 720 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_721 = 721 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_722 = 722 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_723 = 723 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_724 = 724 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_725 = 725 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_726 = 726 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_727 = 727 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_728 = 728 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_729 = 729 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_730 = 730 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_731 = 731 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_732 = 732 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_733 = 733 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_734 = 734 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_735 = 735 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_736 = 736 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_737 = 737 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_738 = 738 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_739 = 739 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_740 = 740 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_741 = 741 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_742 = 742 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_743 = 743 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_744 = 744 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_745 = 745 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_746 = 746 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_747 = 747 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_748 = 748 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_749 = 749 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_750 = 750 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_751 = 751 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_752 = 752 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_753 = 753 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_754 = 754 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_755 = 755 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_756 = 756 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_757 = 757 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_758 = 758 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_759 = 759 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_760 = 760 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_761 = 761 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_762 = 762 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_763 = 763 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_764 = 764 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_765 = 765 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_766 = 766 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_767 = 767 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_768 = 768 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_769 = 769 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_770 = 770 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_771 = 771 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_772 = 772 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_773 = 773 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_774 = 774 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_775 = 775 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_776 = 776 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_777 = 777 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_778 = 778 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_779 = 779 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_780 = 780 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_781 = 781 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_782 = 782 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_783 = 783 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_784 = 784 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_785 = 785 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_786 = 786 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_787 = 787 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_788 = 788 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_789 = 789 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_790 = 790 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_791 = 791 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_792 = 792 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_793 = 793 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_794 = 794 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_795 = 795 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_796 = 796 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_797 = 797 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_798 = 798 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_799 = 799 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_800 = 800 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_801 = 801 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_802 = 802 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_803 = 803 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_804 = 804 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_805 = 805 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_806 = 806 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_807 = 807 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_808 = 808 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_809 = 809 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_810 = 810 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_811 = 811 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_812 = 812 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_813 = 813 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_814 = 814 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_815 = 815 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_816 = 816 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_817 = 817 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_818 = 818 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_819 = 819 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_820 = 820 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_821 = 821 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_822 = 822 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_823 = 823 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_824 = 824 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_825 = 825 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_826 = 826 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_827 = 827 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_828 = 828 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_829 = 829 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_830 = 830 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_831 = 831 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_832 = 832 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_833 = 833 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_834 = 834 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_835 = 835 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_836 = 836 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_837 = 837 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_838 = 838 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_839 = 839 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_840 = 840 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_841 = 841 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_842 = 842 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_843 = 843 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_844 = 844 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_845 = 845 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_846 = 846 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_847 = 847 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_848 = 848 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_849 = 849 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_850 = 850 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_851 = 851 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_852 = 852 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_853 = 853 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_854 = 854 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_855 = 855 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_856 = 856 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_857 = 857 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_858 = 858 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_859 = 859 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_860 = 860 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_861 = 861 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_862 = 862 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_863 = 863 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_864 = 864 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_865 = 865 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_866 = 866 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_867 = 867 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_868 = 868 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_869 = 869 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_870 = 870 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_871 = 871 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_872 = 872 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_873 = 873 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_874 = 874 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_875 = 875 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_876 = 876 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_877 = 877 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_878 = 878 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_879 = 879 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_880 = 880 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_881 = 881 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_882 = 882 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_883 = 883 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_884 = 884 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_885 = 885 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_886 = 886 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_887 = 887 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_888 = 888 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_889 = 889 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_890 = 890 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_891 = 891 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_892 = 892 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_893 = 893 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_894 = 894 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_895 = 895 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_896 = 896 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_897 = 897 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_898 = 898 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_899 = 899 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_900 = 900 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_901 = 901 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_902 = 902 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_903 = 903 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_904 = 904 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_905 = 905 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_906 = 906 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_907 = 907 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_908 = 908 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_909 = 909 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_910 = 910 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_911 = 911 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_912 = 912 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_913 = 913 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_914 = 914 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_915 = 915 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_916 = 916 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_917 = 917 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_918 = 918 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_919 = 919 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_920 = 920 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_921 = 921 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_922 = 922 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_923 = 923 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_924 = 924 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_925 = 925 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_926 = 926 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_927 = 927 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_928 = 928 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_929 = 929 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_930 = 930 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_931 = 931 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_932 = 932 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_933 = 933 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_934 = 934 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_935 = 935 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_936 = 936 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_937 = 937 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_938 = 938 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_939 = 939 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_940 = 940 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_941 = 941 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_942 = 942 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_943 = 943 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_944 = 944 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_945 = 945 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_946 = 946 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_947 = 947 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_948 = 948 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_949 = 949 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_950 = 950 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_951 = 951 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_952 = 952 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_953 = 953 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_954 = 954 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_955 = 955 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_956 = 956 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_957 = 957 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_958 = 958 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_959 = 959 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_960 = 960 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_961 = 961 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_962 = 962 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_963 = 963 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_964 = 964 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_965 = 965 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_966 = 966 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_967 = 967 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_968 = 968 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_969 = 969 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_970 = 970 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_971 = 971 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_972 = 972 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_973 = 973 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_974 = 974 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_975 = 975 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_976 = 976 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_977 = 977 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_978 = 978 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_979 = 979 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_980 = 980 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_981 = 981 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_982 = 982 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_983 = 983 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_984 = 984 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_985 = 985 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_986 = 986 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_987 = 987 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_988 = 988 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_989 = 989 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_990 = 990 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_991 = 991 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_992 = 992 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_993 = 993 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_994 = 994 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_995 = 995 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_996 = 996 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_997 = 997 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_998 = 998 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_999 = 999 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000 = 1000 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto
new file mode 100644
index 0000000000..c115b11171
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import.proto
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which is imported by unittest.proto to test importing.
+
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do
+// "using namespace unittest_import = protobuf_unittest_import".
+package protobuf_unittest_import;
+
+option optimize_for = SPEED;
+
+// Excercise the java_package option.
+option java_package = "com.google.protobuf.test";
+
+// Do not set a java_outer_classname here to verify that Proto2 works without
+// one.
+
+// Test public import
+import public "google/protobuf/unittest_import_public.proto";
+
+message ImportMessage {
+ optional int32 d = 1;
+}
+
+enum ImportEnum {
+ IMPORT_FOO = 7;
+ IMPORT_BAR = 8;
+ IMPORT_BAZ = 9;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto
new file mode 100644
index 0000000000..81b117fe84
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_lite.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+import public "google/protobuf/unittest_import_public_lite.proto";
+
+message ImportMessageLite {
+ optional int32 d = 1;
+}
+
+enum ImportEnumLite {
+ IMPORT_LITE_FOO = 7;
+ IMPORT_LITE_BAR = 8;
+ IMPORT_LITE_BAZ = 9;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000000..ea5d1b13fe
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+
+message PublicImportMessage {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000000..d077563cbd
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_import_public_lite.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message PublicImportMessageLite {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto
new file mode 100644
index 0000000000..a1764aac8d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite.proto
@@ -0,0 +1,360 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest_import_lite.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+// Same as TestAllTypes but with the lite runtime.
+message TestAllTypesLite {
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessageLite optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessageLite
+ optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnumLite optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessageLite repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessageLite
+ repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnumLite repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR];
+ optional ForeignEnumLite default_foreign_enum = 82
+ [default = FOREIGN_LITE_BAR];
+ optional protobuf_unittest_import.ImportEnumLite
+ default_import_enum = 83 [default = IMPORT_LITE_BAR];
+
+ optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+ optional string default_cord = 85 [ctype=CORD,default="123"];
+}
+
+message ForeignMessageLite {
+ optional int32 c = 1;
+}
+
+enum ForeignEnumLite {
+ FOREIGN_LITE_FOO = 4;
+ FOREIGN_LITE_BAR = 5;
+ FOREIGN_LITE_BAZ = 6;
+}
+
+message TestPackedTypesLite {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnumLite packed_enum = 103 [packed = true];
+}
+
+message TestAllExtensionsLite {
+ extensions 1 to max;
+}
+
+extend TestAllExtensionsLite {
+ // Singular
+ optional int32 optional_int32_extension_lite = 1;
+ optional int64 optional_int64_extension_lite = 2;
+ optional uint32 optional_uint32_extension_lite = 3;
+ optional uint64 optional_uint64_extension_lite = 4;
+ optional sint32 optional_sint32_extension_lite = 5;
+ optional sint64 optional_sint64_extension_lite = 6;
+ optional fixed32 optional_fixed32_extension_lite = 7;
+ optional fixed64 optional_fixed64_extension_lite = 8;
+ optional sfixed32 optional_sfixed32_extension_lite = 9;
+ optional sfixed64 optional_sfixed64_extension_lite = 10;
+ optional float optional_float_extension_lite = 11;
+ optional double optional_double_extension_lite = 12;
+ optional bool optional_bool_extension_lite = 13;
+ optional string optional_string_extension_lite = 14;
+ optional bytes optional_bytes_extension_lite = 15;
+
+ optional group OptionalGroup_extension_lite = 16 {
+ optional int32 a = 17;
+ }
+
+ optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
+ = 18;
+ optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
+ optional protobuf_unittest_import.ImportMessageLite
+ optional_import_message_extension_lite = 20;
+
+ optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
+ optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
+ optional protobuf_unittest_import.ImportEnumLite
+ optional_import_enum_extension_lite = 23;
+
+ optional string optional_string_piece_extension_lite = 24
+ [ctype=STRING_PIECE];
+ optional string optional_cord_extension_lite = 25 [ctype=CORD];
+
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message_extension_lite = 26;
+
+ optional TestAllTypesLite.NestedMessage
+ optional_lazy_message_extension_lite = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32_extension_lite = 31;
+ repeated int64 repeated_int64_extension_lite = 32;
+ repeated uint32 repeated_uint32_extension_lite = 33;
+ repeated uint64 repeated_uint64_extension_lite = 34;
+ repeated sint32 repeated_sint32_extension_lite = 35;
+ repeated sint64 repeated_sint64_extension_lite = 36;
+ repeated fixed32 repeated_fixed32_extension_lite = 37;
+ repeated fixed64 repeated_fixed64_extension_lite = 38;
+ repeated sfixed32 repeated_sfixed32_extension_lite = 39;
+ repeated sfixed64 repeated_sfixed64_extension_lite = 40;
+ repeated float repeated_float_extension_lite = 41;
+ repeated double repeated_double_extension_lite = 42;
+ repeated bool repeated_bool_extension_lite = 43;
+ repeated string repeated_string_extension_lite = 44;
+ repeated bytes repeated_bytes_extension_lite = 45;
+
+ repeated group RepeatedGroup_extension_lite = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
+ = 48;
+ repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
+ repeated protobuf_unittest_import.ImportMessageLite
+ repeated_import_message_extension_lite = 50;
+
+ repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
+ repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
+ repeated protobuf_unittest_import.ImportEnumLite
+ repeated_import_enum_extension_lite = 53;
+
+ repeated string repeated_string_piece_extension_lite = 54
+ [ctype=STRING_PIECE];
+ repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
+
+ repeated TestAllTypesLite.NestedMessage
+ repeated_lazy_message_extension_lite = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32_extension_lite = 61 [default = 41 ];
+ optional int64 default_int64_extension_lite = 62 [default = 42 ];
+ optional uint32 default_uint32_extension_lite = 63 [default = 43 ];
+ optional uint64 default_uint64_extension_lite = 64 [default = 44 ];
+ optional sint32 default_sint32_extension_lite = 65 [default = -45 ];
+ optional sint64 default_sint64_extension_lite = 66 [default = 46 ];
+ optional fixed32 default_fixed32_extension_lite = 67 [default = 47 ];
+ optional fixed64 default_fixed64_extension_lite = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32_extension_lite = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50 ];
+ optional float default_float_extension_lite = 71 [default = 51.5 ];
+ optional double default_double_extension_lite = 72 [default = 52e3 ];
+ optional bool default_bool_extension_lite = 73 [default = true ];
+ optional string default_string_extension_lite = 74 [default = "hello"];
+ optional bytes default_bytes_extension_lite = 75 [default = "world"];
+
+ optional TestAllTypesLite.NestedEnum
+ default_nested_enum_extension_lite = 81 [default = BAR];
+ optional ForeignEnumLite
+ default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
+ optional protobuf_unittest_import.ImportEnumLite
+ default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
+
+ optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
+ default="abc"];
+ optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
+}
+
+message TestPackedExtensionsLite {
+ extensions 1 to max;
+}
+
+extend TestPackedExtensionsLite {
+ repeated int32 packed_int32_extension_lite = 90 [packed = true];
+ repeated int64 packed_int64_extension_lite = 91 [packed = true];
+ repeated uint32 packed_uint32_extension_lite = 92 [packed = true];
+ repeated uint64 packed_uint64_extension_lite = 93 [packed = true];
+ repeated sint32 packed_sint32_extension_lite = 94 [packed = true];
+ repeated sint64 packed_sint64_extension_lite = 95 [packed = true];
+ repeated fixed32 packed_fixed32_extension_lite = 96 [packed = true];
+ repeated fixed64 packed_fixed64_extension_lite = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32_extension_lite = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64_extension_lite = 99 [packed = true];
+ repeated float packed_float_extension_lite = 100 [packed = true];
+ repeated double packed_double_extension_lite = 101 [packed = true];
+ repeated bool packed_bool_extension_lite = 102 [packed = true];
+ repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
+}
+
+message TestNestedExtensionLite {
+ extend TestAllExtensionsLite {
+ optional int32 nested_extension = 12345;
+ }
+}
+
+// Test that deprecated fields work. We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedLite {
+ optional int32 deprecated_field = 1 [deprecated = true];
+}
+
+// See the comments of the same type in unittest.proto.
+message TestParsingMergeLite {
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypesLite field1 = 1;
+ repeated TestAllTypesLite field2 = 2;
+ repeated TestAllTypesLite field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypesLite field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypesLite field1 = 21;
+ }
+ repeated TestAllTypesLite ext1 = 1000;
+ repeated TestAllTypesLite ext2 = 1001;
+ }
+ required TestAllTypesLite required_all_types = 1;
+ optional TestAllTypesLite optional_all_types = 2;
+ repeated TestAllTypesLite repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypesLite optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypesLite repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMergeLite {
+ optional TestAllTypesLite optional_ext = 1000;
+ repeated TestAllTypesLite repeated_ext = 1001;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
new file mode 100644
index 0000000000..d52cb8cc36
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Tests that a "lite" message can import a regular message.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+message TestLiteImportsNonlite {
+ optional TestAllTypes message = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto
new file mode 100644
index 0000000000..3497f09fa6
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_mset.proto
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing message_set_wire_format.
+
+package protobuf_unittest;
+
+option optimize_for = SPEED;
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message TestMessageSetContainer {
+ optional TestMessageSet message_set = 1;
+}
+
+message TestMessageSetExtension1 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension1 message_set_extension = 1545008;
+ }
+ optional int32 i = 15;
+}
+
+message TestMessageSetExtension2 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension2 message_set_extension = 1547769;
+ }
+ optional string str = 25;
+}
+
+// MessageSet wire format is equivalent to this.
+message RawMessageSet {
+ repeated group Item = 1 {
+ required int32 type_id = 2;
+ required bytes message = 3;
+ }
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto
new file mode 100644
index 0000000000..cffb4122c5
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_no_generic_services.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+package google.protobuf.no_generic_services_test;
+
+// *_generic_services are false by default.
+
+message TestMessage {
+ optional int32 a = 1;
+ extensions 1000 to max;
+}
+
+enum TestEnum {
+ FOO = 1;
+}
+
+extend TestMessage {
+ optional int32 test_extension = 1000;
+}
+
+service TestService {
+ rpc Foo(TestMessage) returns(TestMessage);
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto
new file mode 100644
index 0000000000..feecbef8d4
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/more_protos/src/proto/google/protobuf/unittest_optimize_for.proto
@@ -0,0 +1,61 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which uses optimize_for = CODE_SIZE.
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+option optimize_for = CODE_SIZE;
+
+message TestOptimizedForSize {
+ optional int32 i = 1;
+ optional ForeignMessage msg = 19;
+
+ extensions 1000 to max;
+
+ extend TestOptimizedForSize {
+ optional int32 test_extension = 1234;
+ optional TestRequiredOptimizedForSize test_extension2 = 1235;
+ }
+}
+
+message TestRequiredOptimizedForSize {
+ required int32 x = 1;
+}
+
+message TestOptionalOptimizedForSize {
+ optional TestRequiredOptimizedForSize o = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/pom.xml b/third_party/protobuf/java/compatibility_tests/v2.5.0/pom.xml
new file mode 100644
index 0000000000..83a7563afd
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-test-suite</artifactId>
+ <version>2.5.0</version>
+ <name>Protocol Buffer Java API compatibility tests</name>
+ <packaging>pom</packaging>
+ <modules>
+ <module>protos</module>
+ <module>more_protos</module>
+ <module>tests</module>
+ </modules>
+ <properties>
+ <protoc.path>protoc</protoc.path>
+ <protobuf.version>2.5.0</protobuf.version>
+
+ <protos.protoc.path>${protoc.path}</protos.protoc.path>
+ <protos.protobuf.version>${protobuf.version}</protos.protobuf.version>
+
+ <more_protos.protoc.path>${protoc.path}</more_protos.protoc.path>
+ <more_protos.protobuf.version>${protobuf.version}</more_protos.protobuf.version>
+
+ <tests.protobuf.version>${protobuf.version}</tests.protobuf.version>
+
+ <protobuf.test.source.path>.</protobuf.test.source.path>
+ </properties>
+</project>
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/pom.xml b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/pom.xml
new file mode 100644
index 0000000000..a22e91ed1d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-test-suite</artifactId>
+ <version>2.5.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-protos</artifactId>
+ <version>2.5.0</version>
+
+ <name>Protos for Compatibility test</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>${protos.protobuf.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.0</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <tasks>
+ <mkdir dir="target/generated-sources" />
+ <exec executable="${protos.protoc.path}">
+ <arg value="--java_out=target/generated-sources" />
+ <arg value="--proto_path=src/proto" />
+ <arg value="src/proto/google/protobuf/unittest_custom_options.proto" />
+ <arg value="src/proto/google/protobuf/unittest_enormous_descriptor.proto" />
+ <arg value="src/proto/google/protobuf/unittest_import.proto" />
+ <arg value="src/proto/google/protobuf/unittest_import_public.proto" />
+ <arg value="src/proto/google/protobuf/unittest_mset.proto" />
+ <arg value="src/proto/google/protobuf/unittest_no_generic_services.proto" />
+ <arg value="src/proto/com/google/protobuf/nested_builders_test.proto" />
+ <arg value="src/proto/com/google/protobuf/nested_extension.proto" />
+ <arg value="src/proto/com/google/protobuf/non_nested_extension.proto" />
+ <arg value="src/proto/com/google/protobuf/test_bad_identifiers.proto" />
+ </exec>
+ </tasks>
+ <sourceRoot>target/generated-sources</sourceRoot>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto
new file mode 100644
index 0000000000..9a040145a6
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/multiple_files_test.proto
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// A proto file which tests the java_multiple_files option.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "MultipleFilesTestProto";
+
+message MessageWithNoOuter {
+ message NestedMessage {
+ optional int32 i = 1;
+ }
+ enum NestedEnum {
+ BAZ = 3;
+ }
+ optional NestedMessage nested = 1;
+ repeated TestAllTypes foreign = 2;
+ optional NestedEnum nested_enum = 3;
+ optional EnumWithNoOuter foreign_enum = 4;
+}
+
+enum EnumWithNoOuter {
+ FOO = 1;
+ BAR = 2;
+}
+
+service ServiceWithNoOuter {
+ rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
+}
+
+extend TestAllExtensions {
+ optional int32 extension_with_outer = 1234567;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto
new file mode 100644
index 0000000000..abffb9d2ba
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_builders_test.proto
@@ -0,0 +1,53 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+//
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "NestedBuilders";
+
+
+message Vehicle {
+ optional Engine engine = 1;
+ repeated Wheel wheel = 2;
+}
+
+message Engine {
+ optional int32 cylinder = 1;
+ optional int32 liters = 2;
+}
+
+message Wheel {
+ optional int32 radius = 1;
+ optional int32 width = 2;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto
new file mode 100644
index 0000000000..9fe5d560c9
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension.proto
@@ -0,0 +1,45 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions. Note that this must be defined in
+// a separate file to properly test the initialization of the outer class.
+
+
+import "com/google/protobuf/non_nested_extension.proto";
+
+package protobuf_unittest;
+
+message MyNestedExtension {
+ extend MessageToBeExtended {
+ optional MessageToBeExtended recursiveExtension = 2;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto
new file mode 100644
index 0000000000..16ee46e57d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/nested_extension_lite.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions for a MessageLite messages. Note that
+// this must be defined in a separate file to properly test the initialization
+// of the outer class.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+import "com/google/protobuf/non_nested_extension_lite.proto";
+
+message MyNestedExtensionLite {
+ extend MessageLiteToBeExtended {
+ optional MessageLiteToBeExtended recursiveExtensionLite = 3;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto
new file mode 100644
index 0000000000..f61b419bc2
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension.proto
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions.
+
+
+package protobuf_unittest;
+
+message MessageToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtension {
+}
+
+extend MessageToBeExtended {
+ optional MyNonNestedExtension nonNestedExtension = 1;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
new file mode 100644
index 0000000000..3c82659b5e
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/non_nested_extension_lite.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions for a MessageLite messages.
+
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message MessageLiteToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtensionLite {
+}
+
+extend MessageLiteToBeExtended {
+ optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
new file mode 100644
index 0000000000..6e67d97a69
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/com/google/protobuf/test_bad_identifiers.proto
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the java code generator.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+package io_protocol_tests;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TestBadIdentifiersProto";
+
+message TestMessage {
+}
+
+message Descriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ message NestedDescriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ }
+ optional NestedDescriptor nested_descriptor = 2;
+}
+
+message Parser {
+ enum ParserEnum {
+ PARSER = 1;
+ }
+ optional ParserEnum parser = 1;
+}
+
+message Deprecated {
+ enum TestEnum {
+ FOO = 1;
+ }
+
+ optional int32 field1 = 1 [deprecated=true];
+ optional TestEnum field2 = 2 [deprecated=true];
+ optional TestMessage field3 = 3 [deprecated=true];
+}
+
+message Override {
+ optional int32 override = 1;
+}
+
+message Object {
+ optional int32 object = 1;
+ optional string string_object = 2;
+}
+
+message String {
+ optional string string = 1;
+}
+
+message Integer {
+ optional int32 integer = 1;
+}
+
+message Long {
+ optional int32 long = 1;
+}
+
+message Float {
+ optional float float = 1;
+}
+
+message Double {
+ optional double double = 1;
+}
+
+service TestConflictingMethodNames {
+ rpc Override(TestMessage) returns (TestMessage);
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
new file mode 100644
index 0000000000..a785f79faf
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/descriptor.proto
@@ -0,0 +1,620 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// The messages in this file describe the definitions found in .proto files.
+// A valid .proto file can be translated directly to a FileDescriptorProto
+// without any other information (e.g. without reading its imports).
+
+
+
+package google.protobuf;
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DescriptorProtos";
+
+// descriptor.proto must be optimized for speed because reflection-based
+// algorithms don't work during bootstrapping.
+option optimize_for = SPEED;
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+message FileDescriptorSet {
+ repeated FileDescriptorProto file = 1;
+}
+
+// Describes a complete .proto file.
+message FileDescriptorProto {
+ optional string name = 1; // file name, relative to root of source tree
+ optional string package = 2; // e.g. "foo", "foo.bar", etc.
+
+ // Names of files imported by this file.
+ repeated string dependency = 3;
+ // Indexes of the public imported files in the dependency list above.
+ repeated int32 public_dependency = 10;
+ // Indexes of the weak imported files in the dependency list.
+ // For Google-internal migration only. Do not use.
+ repeated int32 weak_dependency = 11;
+
+ // All top-level definitions in this file.
+ repeated DescriptorProto message_type = 4;
+ repeated EnumDescriptorProto enum_type = 5;
+ repeated ServiceDescriptorProto service = 6;
+ repeated FieldDescriptorProto extension = 7;
+
+ optional FileOptions options = 8;
+
+ // This field contains optional information about the original source code.
+ // You may safely remove this entire field whithout harming runtime
+ // functionality of the descriptors -- the information is needed only by
+ // development tools.
+ optional SourceCodeInfo source_code_info = 9;
+}
+
+// Describes a message type.
+message DescriptorProto {
+ optional string name = 1;
+
+ repeated FieldDescriptorProto field = 2;
+ repeated FieldDescriptorProto extension = 6;
+
+ repeated DescriptorProto nested_type = 3;
+ repeated EnumDescriptorProto enum_type = 4;
+
+ message ExtensionRange {
+ optional int32 start = 1;
+ optional int32 end = 2;
+ }
+ repeated ExtensionRange extension_range = 5;
+
+ optional MessageOptions options = 7;
+}
+
+// Describes a field within a message.
+message FieldDescriptorProto {
+ enum Type {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ TYPE_DOUBLE = 1;
+ TYPE_FLOAT = 2;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ TYPE_INT64 = 3;
+ TYPE_UINT64 = 4;
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ TYPE_INT32 = 5;
+ TYPE_FIXED64 = 6;
+ TYPE_FIXED32 = 7;
+ TYPE_BOOL = 8;
+ TYPE_STRING = 9;
+ TYPE_GROUP = 10; // Tag-delimited aggregate.
+ TYPE_MESSAGE = 11; // Length-delimited aggregate.
+
+ // New in version 2.
+ TYPE_BYTES = 12;
+ TYPE_UINT32 = 13;
+ TYPE_ENUM = 14;
+ TYPE_SFIXED32 = 15;
+ TYPE_SFIXED64 = 16;
+ TYPE_SINT32 = 17; // Uses ZigZag encoding.
+ TYPE_SINT64 = 18; // Uses ZigZag encoding.
+ };
+
+ enum Label {
+ // 0 is reserved for errors
+ LABEL_OPTIONAL = 1;
+ LABEL_REQUIRED = 2;
+ LABEL_REPEATED = 3;
+ // TODO(sanjay): Should we add LABEL_MAP?
+ };
+
+ optional string name = 1;
+ optional int32 number = 3;
+ optional Label label = 4;
+
+ // If type_name is set, this need not be set. If both this and type_name
+ // are set, this must be either TYPE_ENUM or TYPE_MESSAGE.
+ optional Type type = 5;
+
+ // For message and enum types, this is the name of the type. If the name
+ // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+ // rules are used to find the type (i.e. first the nested types within this
+ // message are searched, then within the parent, on up to the root
+ // namespace).
+ optional string type_name = 6;
+
+ // For extensions, this is the name of the type being extended. It is
+ // resolved in the same manner as type_name.
+ optional string extendee = 2;
+
+ // For numeric types, contains the original text representation of the value.
+ // For booleans, "true" or "false".
+ // For strings, contains the default text contents (not escaped in any way).
+ // For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+ // TODO(kenton): Base-64 encode?
+ optional string default_value = 7;
+
+ optional FieldOptions options = 8;
+}
+
+// Describes an enum type.
+message EnumDescriptorProto {
+ optional string name = 1;
+
+ repeated EnumValueDescriptorProto value = 2;
+
+ optional EnumOptions options = 3;
+}
+
+// Describes a value within an enum.
+message EnumValueDescriptorProto {
+ optional string name = 1;
+ optional int32 number = 2;
+
+ optional EnumValueOptions options = 3;
+}
+
+// Describes a service.
+message ServiceDescriptorProto {
+ optional string name = 1;
+ repeated MethodDescriptorProto method = 2;
+
+ optional ServiceOptions options = 3;
+}
+
+// Describes a method of a service.
+message MethodDescriptorProto {
+ optional string name = 1;
+
+ // Input and output type names. These are resolved in the same way as
+ // FieldDescriptorProto.type_name, but must refer to a message type.
+ optional string input_type = 2;
+ optional string output_type = 3;
+
+ optional MethodOptions options = 4;
+}
+
+
+// ===================================================================
+// Options
+
+// Each of the definitions above may have "options" attached. These are
+// just annotations which may cause code to be generated slightly differently
+// or may contain hints for code that manipulates protocol messages.
+//
+// Clients may define custom options as extensions of the *Options messages.
+// These extensions may not yet be known at parsing time, so the parser cannot
+// store the values in them. Instead it stores them in a field in the *Options
+// message called uninterpreted_option. This field must have the same name
+// across all *Options messages. We then use this field to populate the
+// extensions when we build a descriptor, at which point all protos have been
+// parsed and so all extensions are known.
+//
+// Extension numbers for custom options may be chosen as follows:
+// * For options which will only be used within a single application or
+// organization, or for experimental options, use field numbers 50000
+// through 99999. It is up to you to ensure that you do not use the
+// same number for multiple options.
+// * For options which will be published and used publicly by multiple
+// independent entities, e-mail protobuf-global-extension-registry@google.com
+// to reserve extension numbers. Simply provide your project name (e.g.
+// Object-C plugin) and your porject website (if available) -- there's no need
+// to explain how you intend to use them. Usually you only need one extension
+// number. You can declare multiple options with only one extension number by
+// putting them in a sub-message. See the Custom Options section of the docs
+// for examples:
+// http://code.google.com/apis/protocolbuffers/docs/proto.html#options
+// If this turns out to be popular, a web service will be set up
+// to automatically assign option numbers.
+
+
+message FileOptions {
+
+ // Sets the Java package where classes generated from this .proto will be
+ // placed. By default, the proto package is used, but this is often
+ // inappropriate because proto packages do not normally start with backwards
+ // domain names.
+ optional string java_package = 1;
+
+
+ // If set, all the classes from the .proto file are wrapped in a single
+ // outer class with the given name. This applies to both Proto1
+ // (equivalent to the old "--one_java_file" option) and Proto2 (where
+ // a .proto always translates to a single class, but you may want to
+ // explicitly choose the class name).
+ optional string java_outer_classname = 8;
+
+ // If set true, then the Java code generator will generate a separate .java
+ // file for each top-level message, enum, and service defined in the .proto
+ // file. Thus, these types will *not* be nested inside the outer class
+ // named by java_outer_classname. However, the outer class will still be
+ // generated to contain the file's getDescriptor() method as well as any
+ // top-level extensions defined in the file.
+ optional bool java_multiple_files = 10 [default=false];
+
+ // If set true, then the Java code generator will generate equals() and
+ // hashCode() methods for all messages defined in the .proto file. This is
+ // purely a speed optimization, as the AbstractMessage base class includes
+ // reflection-based implementations of these methods.
+ optional bool java_generate_equals_and_hash = 20 [default=false];
+
+ // Generated classes can be optimized for speed or code size.
+ enum OptimizeMode {
+ SPEED = 1; // Generate complete code for parsing, serialization,
+ // etc.
+ CODE_SIZE = 2; // Use ReflectionOps to implement these methods.
+ LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+ }
+ optional OptimizeMode optimize_for = 9 [default=SPEED];
+
+ // Sets the Go package where structs generated from this .proto will be
+ // placed. There is no default.
+ optional string go_package = 11;
+
+
+
+ // Should generic services be generated in each language? "Generic" services
+ // are not specific to any particular RPC system. They are generated by the
+ // main code generators in each language (without additional plugins).
+ // Generic services were the only kind of service generation supported by
+ // early versions of proto2.
+ //
+ // Generic services are now considered deprecated in favor of using plugins
+ // that generate code specific to your particular RPC system. Therefore,
+ // these default to false. Old code which depends on generic services should
+ // explicitly set them to true.
+ optional bool cc_generic_services = 16 [default=false];
+ optional bool java_generic_services = 17 [default=false];
+ optional bool py_generic_services = 18 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MessageOptions {
+ // Set true to use the old proto1 MessageSet wire format for extensions.
+ // This is provided for backwards-compatibility with the MessageSet wire
+ // format. You should not use this for any other reason: It's less
+ // efficient, has fewer features, and is more complicated.
+ //
+ // The message must be defined exactly as follows:
+ // message Foo {
+ // option message_set_wire_format = true;
+ // extensions 4 to max;
+ // }
+ // Note that the message cannot have any defined fields; MessageSets only
+ // have extensions.
+ //
+ // All extensions of your type must be singular messages; e.g. they cannot
+ // be int32s, enums, or repeated messages.
+ //
+ // Because this is an option, the above two restrictions are not enforced by
+ // the protocol compiler.
+ optional bool message_set_wire_format = 1 [default=false];
+
+ // Disables the generation of the standard "descriptor()" accessor, which can
+ // conflict with a field of the same name. This is meant to make migration
+ // from proto1 easier; new code should avoid fields named "descriptor".
+ optional bool no_standard_descriptor_accessor = 2 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message FieldOptions {
+ // The ctype option instructs the C++ code generator to use a different
+ // representation of the field than it normally would. See the specific
+ // options below. This option is not yet implemented in the open source
+ // release -- sorry, we'll try to include it in a future version!
+ optional CType ctype = 1 [default = STRING];
+ enum CType {
+ // Default mode.
+ STRING = 0;
+
+ CORD = 1;
+
+ STRING_PIECE = 2;
+ }
+ // The packed option can be enabled for repeated primitive fields to enable
+ // a more efficient representation on the wire. Rather than repeatedly
+ // writing the tag and type for each element, the entire array is encoded as
+ // a single length-delimited blob.
+ optional bool packed = 2;
+
+
+
+ // Should this field be parsed lazily? Lazy applies only to message-type
+ // fields. It means that when the outer message is initially parsed, the
+ // inner message's contents will not be parsed but instead stored in encoded
+ // form. The inner message will actually be parsed when it is first accessed.
+ //
+ // This is only a hint. Implementations are free to choose whether to use
+ // eager or lazy parsing regardless of the value of this option. However,
+ // setting this option true suggests that the protocol author believes that
+ // using lazy parsing on this field is worth the additional bookkeeping
+ // overhead typically needed to implement it.
+ //
+ // This option does not affect the public interface of any generated code;
+ // all method signatures remain the same. Furthermore, thread-safety of the
+ // interface is not affected by this option; const methods remain safe to
+ // call from multiple threads concurrently, while non-const methods continue
+ // to require exclusive access.
+ //
+ //
+ // Note that implementations may choose not to check required fields within
+ // a lazy sub-message. That is, calling IsInitialized() on the outher message
+ // may return true even if the inner message has missing required fields.
+ // This is necessary because otherwise the inner message would have to be
+ // parsed in order to perform the check, defeating the purpose of lazy
+ // parsing. An implementation which chooses not to check required fields
+ // must be consistent about it. That is, for any particular sub-message, the
+ // implementation must either *always* check its required fields, or *never*
+ // check its required fields, regardless of whether or not the message has
+ // been parsed.
+ optional bool lazy = 5 [default=false];
+
+ // Is this field deprecated?
+ // Depending on the target platform, this can emit Deprecated annotations
+ // for accessors, or it will be completely ignored; in the very least, this
+ // is a formalization for deprecating fields.
+ optional bool deprecated = 3 [default=false];
+
+ // EXPERIMENTAL. DO NOT USE.
+ // For "map" fields, the name of the field in the enclosed type that
+ // is the key for this map. For example, suppose we have:
+ // message Item {
+ // required string name = 1;
+ // required string value = 2;
+ // }
+ // message Config {
+ // repeated Item items = 1 [experimental_map_key="name"];
+ // }
+ // In this situation, the map key for Item will be set to "name".
+ // TODO: Fully-implement this, then remove the "experimental_" prefix.
+ optional string experimental_map_key = 9;
+
+ // For Google-internal migration only. Do not use.
+ optional bool weak = 10 [default=false];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumOptions {
+
+ // Set this option to false to disallow mapping different tag names to a same
+ // value.
+ optional bool allow_alias = 2 [default=true];
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message EnumValueOptions {
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message ServiceOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+message MethodOptions {
+
+ // Note: Field numbers 1 through 32 are reserved for Google's internal RPC
+ // framework. We apologize for hoarding these numbers to ourselves, but
+ // we were already using them long before we decided to release Protocol
+ // Buffers.
+
+ // The parser stores options it doesn't recognize here. See above.
+ repeated UninterpretedOption uninterpreted_option = 999;
+
+ // Clients can define custom options in extensions of this message. See above.
+ extensions 1000 to max;
+}
+
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+message UninterpretedOption {
+ // The name of the uninterpreted option. Each string represents a segment in
+ // a dot-separated name. is_extension is true iff a segment represents an
+ // extension (denoted with parentheses in options specs in .proto files).
+ // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+ // "foo.(bar.baz).qux".
+ message NamePart {
+ required string name_part = 1;
+ required bool is_extension = 2;
+ }
+ repeated NamePart name = 2;
+
+ // The value of the uninterpreted option, in whatever type the tokenizer
+ // identified it as during parsing. Exactly one of these should be set.
+ optional string identifier_value = 3;
+ optional uint64 positive_int_value = 4;
+ optional int64 negative_int_value = 5;
+ optional double double_value = 6;
+ optional bytes string_value = 7;
+ optional string aggregate_value = 8;
+}
+
+// ===================================================================
+// Optional source code info
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+message SourceCodeInfo {
+ // A Location identifies a piece of source code in a .proto file which
+ // corresponds to a particular definition. This information is intended
+ // to be useful to IDEs, code indexers, documentation generators, and similar
+ // tools.
+ //
+ // For example, say we have a file like:
+ // message Foo {
+ // optional string foo = 1;
+ // }
+ // Let's look at just the field definition:
+ // optional string foo = 1;
+ // ^ ^^ ^^ ^ ^^^
+ // a bc de f ghi
+ // We have the following locations:
+ // span path represents
+ // [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+ // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+ // [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+ // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+ // [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+ //
+ // Notes:
+ // - A location may refer to a repeated field itself (i.e. not to any
+ // particular index within it). This is used whenever a set of elements are
+ // logically enclosed in a single code segment. For example, an entire
+ // extend block (possibly containing multiple extension definitions) will
+ // have an outer location whose path refers to the "extensions" repeated
+ // field without an index.
+ // - Multiple locations may have the same path. This happens when a single
+ // logical declaration is spread out across multiple places. The most
+ // obvious example is the "extend" block again -- there may be multiple
+ // extend blocks in the same scope, each of which will have the same path.
+ // - A location's span is not always a subset of its parent's span. For
+ // example, the "extendee" of an extension declaration appears at the
+ // beginning of the "extend" block and is shared by all extensions within
+ // the block.
+ // - Just because a location's span is a subset of some other location's span
+ // does not mean that it is a descendent. For example, a "group" defines
+ // both a type and a field in a single declaration. Thus, the locations
+ // corresponding to the type and field and their components will overlap.
+ // - Code which tries to interpret locations should probably be designed to
+ // ignore those that it doesn't understand, as more types of locations could
+ // be recorded in the future.
+ repeated Location location = 1;
+ message Location {
+ // Identifies which part of the FileDescriptorProto was defined at this
+ // location.
+ //
+ // Each element is a field number or an index. They form a path from
+ // the root FileDescriptorProto to the place where the definition. For
+ // example, this path:
+ // [ 4, 3, 2, 7, 1 ]
+ // refers to:
+ // file.message_type(3) // 4, 3
+ // .field(7) // 2, 7
+ // .name() // 1
+ // This is because FileDescriptorProto.message_type has field number 4:
+ // repeated DescriptorProto message_type = 4;
+ // and DescriptorProto.field has field number 2:
+ // repeated FieldDescriptorProto field = 2;
+ // and FieldDescriptorProto.name has field number 1:
+ // optional string name = 1;
+ //
+ // Thus, the above path gives the location of a field name. If we removed
+ // the last element:
+ // [ 4, 3, 2, 7 ]
+ // this path refers to the whole field declaration (from the beginning
+ // of the label to the terminating semicolon).
+ repeated int32 path = 1 [packed=true];
+
+ // Always has exactly three or four elements: start line, start column,
+ // end line (optional, otherwise assumed same as start line), end column.
+ // These are packed into a single field for efficiency. Note that line
+ // and column numbers are zero-based -- typically you will want to add
+ // 1 to each before displaying to a user.
+ repeated int32 span = 2 [packed=true];
+
+ // If this SourceCodeInfo represents a complete declaration, these are any
+ // comments appearing before and after the declaration which appear to be
+ // attached to the declaration.
+ //
+ // A series of line comments appearing on consecutive lines, with no other
+ // tokens appearing on those lines, will be treated as a single comment.
+ //
+ // Only the comment content is provided; comment markers (e.g. //) are
+ // stripped out. For block comments, leading whitespace and an asterisk
+ // will be stripped from the beginning of each line other than the first.
+ // Newlines are included in the output.
+ //
+ // Examples:
+ //
+ // optional int32 foo = 1; // Comment attached to foo.
+ // // Comment attached to bar.
+ // optional int32 bar = 2;
+ //
+ // optional string baz = 3;
+ // // Comment attached to baz.
+ // // Another line attached to baz.
+ //
+ // // Comment attached to qux.
+ // //
+ // // Another line attached to qux.
+ // optional double qux = 4;
+ //
+ // optional string corge = 5;
+ // /* Block comment attached
+ // * to corge. Leading asterisks
+ // * will be removed. */
+ // /* Block comment attached to
+ // * grault. */
+ // optional int32 grault = 6;
+ optional string leading_comments = 3;
+ optional string trailing_comments = 4;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
new file mode 100644
index 0000000000..6eb2d86f51
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest.proto
@@ -0,0 +1,719 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file we will use for unit testing.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true; // auto-added
+
+import "google/protobuf/unittest_import.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do "using namespace unittest = protobuf_unittest".
+package protobuf_unittest;
+
+// Protos optimized for SPEED use a strict superset of the generated code
+// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
+// tests for speed unless explicitly testing code size optimization.
+option optimize_for = SPEED;
+
+option java_outer_classname = "UnittestProto";
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+message TestAllTypes {
+ message NestedMessage {
+ // The field name "b" fails to compile in proto1 because it conflicts with
+ // a local variable named "b" in one of the generated methods. Doh.
+ // This file needs to compile in proto1 to test backwards-compatibility.
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessage optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessage optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnum optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnum optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessage repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnum repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR ];
+ optional ForeignEnum default_foreign_enum = 82 [default = FOREIGN_BAR];
+ optional protobuf_unittest_import.ImportEnum
+ default_import_enum = 83 [default = IMPORT_BAR];
+
+ optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+ optional string default_cord = 85 [ctype=CORD,default="123"];
+}
+
+message TestDeprecatedFields {
+ optional int32 deprecated_int32 = 1 [deprecated=true];
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+ optional int32 c = 1;
+}
+
+enum ForeignEnum {
+ FOREIGN_FOO = 4;
+ FOREIGN_BAR = 5;
+ FOREIGN_BAZ = 6;
+}
+
+message TestAllExtensions {
+ extensions 1 to max;
+}
+
+extend TestAllExtensions {
+ // Singular
+ optional int32 optional_int32_extension = 1;
+ optional int64 optional_int64_extension = 2;
+ optional uint32 optional_uint32_extension = 3;
+ optional uint64 optional_uint64_extension = 4;
+ optional sint32 optional_sint32_extension = 5;
+ optional sint64 optional_sint64_extension = 6;
+ optional fixed32 optional_fixed32_extension = 7;
+ optional fixed64 optional_fixed64_extension = 8;
+ optional sfixed32 optional_sfixed32_extension = 9;
+ optional sfixed64 optional_sfixed64_extension = 10;
+ optional float optional_float_extension = 11;
+ optional double optional_double_extension = 12;
+ optional bool optional_bool_extension = 13;
+ optional string optional_string_extension = 14;
+ optional bytes optional_bytes_extension = 15;
+
+ optional group OptionalGroup_extension = 16 {
+ optional int32 a = 17;
+ }
+
+ optional TestAllTypes.NestedMessage optional_nested_message_extension = 18;
+ optional ForeignMessage optional_foreign_message_extension = 19;
+ optional protobuf_unittest_import.ImportMessage
+ optional_import_message_extension = 20;
+
+ optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
+ optional ForeignEnum optional_foreign_enum_extension = 22;
+ optional protobuf_unittest_import.ImportEnum
+ optional_import_enum_extension = 23;
+
+ optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
+ optional string optional_cord_extension = 25 [ctype=CORD];
+
+ optional protobuf_unittest_import.PublicImportMessage
+ optional_public_import_message_extension = 26;
+
+ optional TestAllTypes.NestedMessage
+ optional_lazy_message_extension = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32_extension = 31;
+ repeated int64 repeated_int64_extension = 32;
+ repeated uint32 repeated_uint32_extension = 33;
+ repeated uint64 repeated_uint64_extension = 34;
+ repeated sint32 repeated_sint32_extension = 35;
+ repeated sint64 repeated_sint64_extension = 36;
+ repeated fixed32 repeated_fixed32_extension = 37;
+ repeated fixed64 repeated_fixed64_extension = 38;
+ repeated sfixed32 repeated_sfixed32_extension = 39;
+ repeated sfixed64 repeated_sfixed64_extension = 40;
+ repeated float repeated_float_extension = 41;
+ repeated double repeated_double_extension = 42;
+ repeated bool repeated_bool_extension = 43;
+ repeated string repeated_string_extension = 44;
+ repeated bytes repeated_bytes_extension = 45;
+
+ repeated group RepeatedGroup_extension = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated TestAllTypes.NestedMessage repeated_nested_message_extension = 48;
+ repeated ForeignMessage repeated_foreign_message_extension = 49;
+ repeated protobuf_unittest_import.ImportMessage
+ repeated_import_message_extension = 50;
+
+ repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+ repeated ForeignEnum repeated_foreign_enum_extension = 52;
+ repeated protobuf_unittest_import.ImportEnum
+ repeated_import_enum_extension = 53;
+
+ repeated string repeated_string_piece_extension = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord_extension = 55 [ctype=CORD];
+
+ repeated TestAllTypes.NestedMessage
+ repeated_lazy_message_extension = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32_extension = 61 [default = 41 ];
+ optional int64 default_int64_extension = 62 [default = 42 ];
+ optional uint32 default_uint32_extension = 63 [default = 43 ];
+ optional uint64 default_uint64_extension = 64 [default = 44 ];
+ optional sint32 default_sint32_extension = 65 [default = -45 ];
+ optional sint64 default_sint64_extension = 66 [default = 46 ];
+ optional fixed32 default_fixed32_extension = 67 [default = 47 ];
+ optional fixed64 default_fixed64_extension = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32_extension = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64_extension = 70 [default = -50 ];
+ optional float default_float_extension = 71 [default = 51.5 ];
+ optional double default_double_extension = 72 [default = 52e3 ];
+ optional bool default_bool_extension = 73 [default = true ];
+ optional string default_string_extension = 74 [default = "hello"];
+ optional bytes default_bytes_extension = 75 [default = "world"];
+
+ optional TestAllTypes.NestedEnum
+ default_nested_enum_extension = 81 [default = BAR];
+ optional ForeignEnum
+ default_foreign_enum_extension = 82 [default = FOREIGN_BAR];
+ optional protobuf_unittest_import.ImportEnum
+ default_import_enum_extension = 83 [default = IMPORT_BAR];
+
+ optional string default_string_piece_extension = 84 [ctype=STRING_PIECE,
+ default="abc"];
+ optional string default_cord_extension = 85 [ctype=CORD, default="123"];
+}
+
+message TestNestedExtension {
+ extend TestAllExtensions {
+ // Check for bug where string extensions declared in tested scope did not
+ // compile.
+ optional string test = 1002 [default="test"];
+ }
+}
+
+// We have separate messages for testing required fields because it's
+// annoying to have to fill in required fields in TestProto in order to
+// do anything with it. Note that we don't need to test every type of
+// required filed because the code output is basically identical to
+// optional fields for all types.
+message TestRequired {
+ required int32 a = 1;
+ optional int32 dummy2 = 2;
+ required int32 b = 3;
+
+ extend TestAllExtensions {
+ optional TestRequired single = 1000;
+ repeated TestRequired multi = 1001;
+ }
+
+ // Pad the field count to 32 so that we can test that IsInitialized()
+ // properly checks multiple elements of has_bits_.
+ optional int32 dummy4 = 4;
+ optional int32 dummy5 = 5;
+ optional int32 dummy6 = 6;
+ optional int32 dummy7 = 7;
+ optional int32 dummy8 = 8;
+ optional int32 dummy9 = 9;
+ optional int32 dummy10 = 10;
+ optional int32 dummy11 = 11;
+ optional int32 dummy12 = 12;
+ optional int32 dummy13 = 13;
+ optional int32 dummy14 = 14;
+ optional int32 dummy15 = 15;
+ optional int32 dummy16 = 16;
+ optional int32 dummy17 = 17;
+ optional int32 dummy18 = 18;
+ optional int32 dummy19 = 19;
+ optional int32 dummy20 = 20;
+ optional int32 dummy21 = 21;
+ optional int32 dummy22 = 22;
+ optional int32 dummy23 = 23;
+ optional int32 dummy24 = 24;
+ optional int32 dummy25 = 25;
+ optional int32 dummy26 = 26;
+ optional int32 dummy27 = 27;
+ optional int32 dummy28 = 28;
+ optional int32 dummy29 = 29;
+ optional int32 dummy30 = 30;
+ optional int32 dummy31 = 31;
+ optional int32 dummy32 = 32;
+
+ required int32 c = 33;
+}
+
+message TestRequiredForeign {
+ optional TestRequired optional_message = 1;
+ repeated TestRequired repeated_message = 2;
+ optional int32 dummy = 3;
+}
+
+// Test that we can use NestedMessage from outside TestAllTypes.
+message TestForeignNested {
+ optional TestAllTypes.NestedMessage foreign_nested = 1;
+}
+
+// TestEmptyMessage is used to test unknown field support.
+message TestEmptyMessage {
+}
+
+// Like above, but declare all field numbers as potential extensions. No
+// actual extensions should ever be defined for this type.
+message TestEmptyMessageWithExtensions {
+ extensions 1 to max;
+}
+
+message TestMultipleExtensionRanges {
+ extensions 42;
+ extensions 4143 to 4243;
+ extensions 65536 to max;
+}
+
+// Test that really large tag numbers don't break anything.
+message TestReallyLargeTagNumber {
+ // The largest possible tag number is 2^28 - 1, since the wire format uses
+ // three bits to communicate wire type.
+ optional int32 a = 1;
+ optional int32 bb = 268435455;
+}
+
+message TestRecursiveMessage {
+ optional TestRecursiveMessage a = 1;
+ optional int32 i = 2;
+}
+
+// Test that mutual recursion works.
+message TestMutualRecursionA {
+ optional TestMutualRecursionB bb = 1;
+}
+
+message TestMutualRecursionB {
+ optional TestMutualRecursionA a = 1;
+ optional int32 optional_int32 = 2;
+}
+
+// Test that groups have disjoint field numbers from their siblings and
+// parents. This is NOT possible in proto1; only proto2. When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in protobuf_unittest_proto.
+message TestDupFieldNumber { // NO_PROTO1
+ optional int32 a = 1; // NO_PROTO1
+ optional group Foo = 2 { optional int32 a = 1; } // NO_PROTO1
+ optional group Bar = 3 { optional int32 a = 1; } // NO_PROTO1
+} // NO_PROTO1
+
+// Additional messages for testing lazy fields.
+message TestEagerMessage {
+ optional TestAllTypes sub_message = 1 [lazy=false];
+}
+message TestLazyMessage {
+ optional TestAllTypes sub_message = 1 [lazy=true];
+}
+
+// Needed for a Python test.
+message TestNestedMessageHasBits {
+ message NestedMessage {
+ repeated int32 nestedmessage_repeated_int32 = 1;
+ repeated ForeignMessage nestedmessage_repeated_foreignmessage = 2;
+ }
+ optional NestedMessage optional_nested_message = 1;
+}
+
+
+// Test an enum that has multiple values with the same number.
+enum TestEnumWithDupValue {
+ option allow_alias = true;
+ FOO1 = 1;
+ BAR1 = 2;
+ BAZ = 3;
+ FOO2 = 1;
+ BAR2 = 2;
+}
+
+// Test an enum with large, unordered values.
+enum TestSparseEnum {
+ SPARSE_A = 123;
+ SPARSE_B = 62374;
+ SPARSE_C = 12589234;
+ SPARSE_D = -15;
+ SPARSE_E = -53452;
+ SPARSE_F = 0;
+ SPARSE_G = 2;
+}
+
+// Test message with CamelCase field names. This violates Protocol Buffer
+// standard style.
+message TestCamelCaseFieldNames {
+ optional int32 PrimitiveField = 1;
+ optional string StringField = 2;
+ optional ForeignEnum EnumField = 3;
+ optional ForeignMessage MessageField = 4;
+ optional string StringPieceField = 5 [ctype=STRING_PIECE];
+ optional string CordField = 6 [ctype=CORD];
+
+ repeated int32 RepeatedPrimitiveField = 7;
+ repeated string RepeatedStringField = 8;
+ repeated ForeignEnum RepeatedEnumField = 9;
+ repeated ForeignMessage RepeatedMessageField = 10;
+ repeated string RepeatedStringPieceField = 11 [ctype=STRING_PIECE];
+ repeated string RepeatedCordField = 12 [ctype=CORD];
+}
+
+
+// We list fields out of order, to ensure that we're using field number and not
+// field index to determine serialization order.
+message TestFieldOrderings {
+ optional string my_string = 11;
+ extensions 2 to 10;
+ optional int64 my_int = 1;
+ extensions 12 to 100;
+ optional float my_float = 101;
+}
+
+
+extend TestFieldOrderings {
+ optional string my_extension_string = 50;
+ optional int32 my_extension_int = 5;
+}
+
+
+message TestExtremeDefaultValues {
+ optional bytes escaped_bytes = 1 [default = "\0\001\a\b\f\n\r\t\v\\\'\"\xfe"];
+ optional uint32 large_uint32 = 2 [default = 0xFFFFFFFF];
+ optional uint64 large_uint64 = 3 [default = 0xFFFFFFFFFFFFFFFF];
+ optional int32 small_int32 = 4 [default = -0x7FFFFFFF];
+ optional int64 small_int64 = 5 [default = -0x7FFFFFFFFFFFFFFF];
+ optional int32 really_small_int32 = 21 [default = -0x80000000];
+ optional int64 really_small_int64 = 22 [default = -0x8000000000000000];
+
+ // The default value here is UTF-8 for "\u1234". (We could also just type
+ // the UTF-8 text directly into this text file rather than escape it, but
+ // lots of people use editors that would be confused by this.)
+ optional string utf8_string = 6 [default = "\341\210\264"];
+
+ // Tests for single-precision floating-point values.
+ optional float zero_float = 7 [default = 0];
+ optional float one_float = 8 [default = 1];
+ optional float small_float = 9 [default = 1.5];
+ optional float negative_one_float = 10 [default = -1];
+ optional float negative_float = 11 [default = -1.5];
+ // Using exponents
+ optional float large_float = 12 [default = 2E8];
+ optional float small_negative_float = 13 [default = -8e-28];
+
+ // Text for nonfinite floating-point values.
+ optional double inf_double = 14 [default = inf];
+ optional double neg_inf_double = 15 [default = -inf];
+ optional double nan_double = 16 [default = nan];
+ optional float inf_float = 17 [default = inf];
+ optional float neg_inf_float = 18 [default = -inf];
+ optional float nan_float = 19 [default = nan];
+
+ // Tests for C++ trigraphs.
+ // Trigraphs should be escaped in C++ generated files, but they should not be
+ // escaped for other languages.
+ // Note that in .proto file, "\?" is a valid way to escape ? in string
+ // literals.
+ optional string cpp_trigraph = 20 [default = "? \? ?? \?? \??? ??/ ?\?-"];
+
+ // String defaults containing the character '\000'
+ optional string string_with_zero = 23 [default = "hel\000lo"];
+ optional bytes bytes_with_zero = 24 [default = "wor\000ld"];
+ optional string string_piece_with_zero = 25 [ctype=STRING_PIECE,
+ default="ab\000c"];
+ optional string cord_with_zero = 26 [ctype=CORD,
+ default="12\0003"];
+}
+
+message SparseEnumMessage {
+ optional TestSparseEnum sparse_enum = 1;
+}
+
+// Test String and Bytes: string is for valid UTF-8 strings
+message OneString {
+ optional string data = 1;
+}
+
+message MoreString {
+ repeated string data = 1;
+}
+
+message OneBytes {
+ optional bytes data = 1;
+}
+
+message MoreBytes {
+ repeated bytes data = 1;
+}
+
+
+// Test messages for packed fields
+
+message TestPackedTypes {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnum packed_enum = 103 [packed = true];
+}
+
+// A message with the same fields as TestPackedTypes, but without packing. Used
+// to test packed <-> unpacked wire compatibility.
+message TestUnpackedTypes {
+ repeated int32 unpacked_int32 = 90 [packed = false];
+ repeated int64 unpacked_int64 = 91 [packed = false];
+ repeated uint32 unpacked_uint32 = 92 [packed = false];
+ repeated uint64 unpacked_uint64 = 93 [packed = false];
+ repeated sint32 unpacked_sint32 = 94 [packed = false];
+ repeated sint64 unpacked_sint64 = 95 [packed = false];
+ repeated fixed32 unpacked_fixed32 = 96 [packed = false];
+ repeated fixed64 unpacked_fixed64 = 97 [packed = false];
+ repeated sfixed32 unpacked_sfixed32 = 98 [packed = false];
+ repeated sfixed64 unpacked_sfixed64 = 99 [packed = false];
+ repeated float unpacked_float = 100 [packed = false];
+ repeated double unpacked_double = 101 [packed = false];
+ repeated bool unpacked_bool = 102 [packed = false];
+ repeated ForeignEnum unpacked_enum = 103 [packed = false];
+}
+
+message TestPackedExtensions {
+ extensions 1 to max;
+}
+
+extend TestPackedExtensions {
+ repeated int32 packed_int32_extension = 90 [packed = true];
+ repeated int64 packed_int64_extension = 91 [packed = true];
+ repeated uint32 packed_uint32_extension = 92 [packed = true];
+ repeated uint64 packed_uint64_extension = 93 [packed = true];
+ repeated sint32 packed_sint32_extension = 94 [packed = true];
+ repeated sint64 packed_sint64_extension = 95 [packed = true];
+ repeated fixed32 packed_fixed32_extension = 96 [packed = true];
+ repeated fixed64 packed_fixed64_extension = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32_extension = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64_extension = 99 [packed = true];
+ repeated float packed_float_extension = 100 [packed = true];
+ repeated double packed_double_extension = 101 [packed = true];
+ repeated bool packed_bool_extension = 102 [packed = true];
+ repeated ForeignEnum packed_enum_extension = 103 [packed = true];
+}
+
+// Used by ExtensionSetTest/DynamicExtensions. The test actually builds
+// a set of extensions to TestAllExtensions dynamically, based on the fields
+// of this message type.
+message TestDynamicExtensions {
+ enum DynamicEnumType {
+ DYNAMIC_FOO = 2200;
+ DYNAMIC_BAR = 2201;
+ DYNAMIC_BAZ = 2202;
+ }
+ message DynamicMessageType {
+ optional int32 dynamic_field = 2100;
+ }
+
+ optional fixed32 scalar_extension = 2000;
+ optional ForeignEnum enum_extension = 2001;
+ optional DynamicEnumType dynamic_enum_extension = 2002;
+
+ optional ForeignMessage message_extension = 2003;
+ optional DynamicMessageType dynamic_message_extension = 2004;
+
+ repeated string repeated_extension = 2005;
+ repeated sint32 packed_extension = 2006 [packed = true];
+}
+
+message TestRepeatedScalarDifferentTagSizes {
+ // Parsing repeated fixed size values used to fail. This message needs to be
+ // used in order to get a tag of the right size; all of the repeated fields
+ // in TestAllTypes didn't trigger the check.
+ repeated fixed32 repeated_fixed32 = 12;
+ // Check for a varint type, just for good measure.
+ repeated int32 repeated_int32 = 13;
+
+ // These have two-byte tags.
+ repeated fixed64 repeated_fixed64 = 2046;
+ repeated int64 repeated_int64 = 2047;
+
+ // Three byte tags.
+ repeated float repeated_float = 262142;
+ repeated uint64 repeated_uint64 = 262143;
+}
+
+// Test that if an optional or required message/group field appears multiple
+// times in the input, they need to be merged.
+message TestParsingMerge {
+ // RepeatedFieldsGenerator defines matching field types as TestParsingMerge,
+ // except that all fields are repeated. In the tests, we will serialize the
+ // RepeatedFieldsGenerator to bytes, and parse the bytes to TestParsingMerge.
+ // Repeated fields in RepeatedFieldsGenerator are expected to be merged into
+ // the corresponding required/optional fields in TestParsingMerge.
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypes field1 = 1;
+ repeated TestAllTypes field2 = 2;
+ repeated TestAllTypes field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypes field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypes field1 = 21;
+ }
+ repeated TestAllTypes ext1 = 1000;
+ repeated TestAllTypes ext2 = 1001;
+ }
+ required TestAllTypes required_all_types = 1;
+ optional TestAllTypes optional_all_types = 2;
+ repeated TestAllTypes repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypes optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypes repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMerge {
+ optional TestAllTypes optional_ext = 1000;
+ repeated TestAllTypes repeated_ext = 1001;
+ }
+}
+
+message TestCommentInjectionMessage {
+ // */ <- This should not close the generated doc comment
+ optional string a = 1 [default="*/ <- Neither should this."];
+}
+
+
+// Test that RPC services work.
+message FooRequest {}
+message FooResponse {}
+
+message FooClientMessage {}
+message FooServerMessage{}
+
+service TestService {
+ rpc Foo(FooRequest) returns (FooResponse);
+ rpc Bar(BarRequest) returns (BarResponse);
+}
+
+
+message BarRequest {}
+message BarResponse {}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
new file mode 100644
index 0000000000..e591d29447
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_custom_options.proto
@@ -0,0 +1,387 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: benjy@google.com (Benjy Weinberger)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file used to test the "custom options" feature of proto2.
+
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option cc_generic_services = true; // auto-added
+option java_generic_services = true; // auto-added
+option py_generic_services = true;
+
+// A custom file option (defined below).
+option (file_opt1) = 9876543210;
+
+import "google/protobuf/descriptor.proto";
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+package protobuf_unittest;
+
+
+// Some simple test custom options of various types.
+
+extend google.protobuf.FileOptions {
+ optional uint64 file_opt1 = 7736974;
+}
+
+extend google.protobuf.MessageOptions {
+ optional int32 message_opt1 = 7739036;
+}
+
+extend google.protobuf.FieldOptions {
+ optional fixed64 field_opt1 = 7740936;
+ // This is useful for testing that we correctly register default values for
+ // extension options.
+ optional int32 field_opt2 = 7753913 [default=42];
+}
+
+extend google.protobuf.EnumOptions {
+ optional sfixed32 enum_opt1 = 7753576;
+}
+
+extend google.protobuf.EnumValueOptions {
+ optional int32 enum_value_opt1 = 1560678;
+}
+
+extend google.protobuf.ServiceOptions {
+ optional sint64 service_opt1 = 7887650;
+}
+
+enum MethodOpt1 {
+ METHODOPT1_VAL1 = 1;
+ METHODOPT1_VAL2 = 2;
+}
+
+extend google.protobuf.MethodOptions {
+ optional MethodOpt1 method_opt1 = 7890860;
+}
+
+// A test message with custom options at all possible locations (and also some
+// regular options, to make sure they interact nicely).
+message TestMessageWithCustomOptions {
+ option message_set_wire_format = false;
+
+ option (message_opt1) = -56;
+
+ optional string field1 = 1 [ctype=CORD,
+ (field_opt1)=8765432109];
+
+ enum AnEnum {
+ option (enum_opt1) = -789;
+
+ ANENUM_VAL1 = 1;
+ ANENUM_VAL2 = 2 [(enum_value_opt1) = 123];
+ }
+}
+
+
+// A test RPC service with custom options at all possible locations (and also
+// some regular options, to make sure they interact nicely).
+message CustomOptionFooRequest {
+}
+
+message CustomOptionFooResponse {
+}
+
+message CustomOptionFooClientMessage {
+}
+
+message CustomOptionFooServerMessage {
+}
+
+service TestServiceWithCustomOptions {
+ option (service_opt1) = -9876543210;
+
+ rpc Foo(CustomOptionFooRequest) returns (CustomOptionFooResponse) {
+ option (method_opt1) = METHODOPT1_VAL2;
+ }
+}
+
+
+
+// Options of every possible field type, so we can test them all exhaustively.
+
+message DummyMessageContainingEnum {
+ enum TestEnumType {
+ TEST_OPTION_ENUM_TYPE1 = 22;
+ TEST_OPTION_ENUM_TYPE2 = -23;
+ }
+}
+
+message DummyMessageInvalidAsOptionType {
+}
+
+extend google.protobuf.MessageOptions {
+ optional bool bool_opt = 7706090;
+ optional int32 int32_opt = 7705709;
+ optional int64 int64_opt = 7705542;
+ optional uint32 uint32_opt = 7704880;
+ optional uint64 uint64_opt = 7702367;
+ optional sint32 sint32_opt = 7701568;
+ optional sint64 sint64_opt = 7700863;
+ optional fixed32 fixed32_opt = 7700307;
+ optional fixed64 fixed64_opt = 7700194;
+ optional sfixed32 sfixed32_opt = 7698645;
+ optional sfixed64 sfixed64_opt = 7685475;
+ optional float float_opt = 7675390;
+ optional double double_opt = 7673293;
+ optional string string_opt = 7673285;
+ optional bytes bytes_opt = 7673238;
+ optional DummyMessageContainingEnum.TestEnumType enum_opt = 7673233;
+ optional DummyMessageInvalidAsOptionType message_type_opt = 7665967;
+}
+
+message CustomOptionMinIntegerValues {
+ option (bool_opt) = false;
+ option (int32_opt) = -0x80000000;
+ option (int64_opt) = -0x8000000000000000;
+ option (uint32_opt) = 0;
+ option (uint64_opt) = 0;
+ option (sint32_opt) = -0x80000000;
+ option (sint64_opt) = -0x8000000000000000;
+ option (fixed32_opt) = 0;
+ option (fixed64_opt) = 0;
+ option (sfixed32_opt) = -0x80000000;
+ option (sfixed64_opt) = -0x8000000000000000;
+}
+
+message CustomOptionMaxIntegerValues {
+ option (bool_opt) = true;
+ option (int32_opt) = 0x7FFFFFFF;
+ option (int64_opt) = 0x7FFFFFFFFFFFFFFF;
+ option (uint32_opt) = 0xFFFFFFFF;
+ option (uint64_opt) = 0xFFFFFFFFFFFFFFFF;
+ option (sint32_opt) = 0x7FFFFFFF;
+ option (sint64_opt) = 0x7FFFFFFFFFFFFFFF;
+ option (fixed32_opt) = 0xFFFFFFFF;
+ option (fixed64_opt) = 0xFFFFFFFFFFFFFFFF;
+ option (sfixed32_opt) = 0x7FFFFFFF;
+ option (sfixed64_opt) = 0x7FFFFFFFFFFFFFFF;
+}
+
+message CustomOptionOtherValues {
+ option (int32_opt) = -100; // To test sign-extension.
+ option (float_opt) = 12.3456789;
+ option (double_opt) = 1.234567890123456789;
+ option (string_opt) = "Hello, \"World\"";
+ option (bytes_opt) = "Hello\0World";
+ option (enum_opt) = TEST_OPTION_ENUM_TYPE2;
+}
+
+message SettingRealsFromPositiveInts {
+ option (float_opt) = 12;
+ option (double_opt) = 154;
+}
+
+message SettingRealsFromNegativeInts {
+ option (float_opt) = -12;
+ option (double_opt) = -154;
+}
+
+// Options of complex message types, themselves combined and extended in
+// various ways.
+
+message ComplexOptionType1 {
+ optional int32 foo = 1;
+ optional int32 foo2 = 2;
+ optional int32 foo3 = 3;
+
+ extensions 100 to max;
+}
+
+message ComplexOptionType2 {
+ optional ComplexOptionType1 bar = 1;
+ optional int32 baz = 2;
+
+ message ComplexOptionType4 {
+ optional int32 waldo = 1;
+
+ extend google.protobuf.MessageOptions {
+ optional ComplexOptionType4 complex_opt4 = 7633546;
+ }
+ }
+
+ optional ComplexOptionType4 fred = 3;
+
+ extensions 100 to max;
+}
+
+message ComplexOptionType3 {
+ optional int32 qux = 1;
+
+ optional group ComplexOptionType5 = 2 {
+ optional int32 plugh = 3;
+ }
+}
+
+extend ComplexOptionType1 {
+ optional int32 quux = 7663707;
+ optional ComplexOptionType3 corge = 7663442;
+}
+
+extend ComplexOptionType2 {
+ optional int32 grault = 7650927;
+ optional ComplexOptionType1 garply = 7649992;
+}
+
+extend google.protobuf.MessageOptions {
+ optional protobuf_unittest.ComplexOptionType1 complex_opt1 = 7646756;
+ optional ComplexOptionType2 complex_opt2 = 7636949;
+ optional ComplexOptionType3 complex_opt3 = 7636463;
+ optional group ComplexOpt6 = 7595468 {
+ optional int32 xyzzy = 7593951;
+ }
+}
+
+// Note that we try various different ways of naming the same extension.
+message VariousComplexOptions {
+ option (.protobuf_unittest.complex_opt1).foo = 42;
+ option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324;
+ option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876;
+ option (complex_opt2).baz = 987;
+ option (complex_opt2).(grault) = 654;
+ option (complex_opt2).bar.foo = 743;
+ option (complex_opt2).bar.(quux) = 1999;
+ option (complex_opt2).bar.(protobuf_unittest.corge).qux = 2008;
+ option (complex_opt2).(garply).foo = 741;
+ option (complex_opt2).(garply).(.protobuf_unittest.quux) = 1998;
+ option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121;
+ option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971;
+ option (complex_opt2).fred.waldo = 321;
+ option (protobuf_unittest.complex_opt3).qux = 9;
+ option (complex_opt3).complexoptiontype5.plugh = 22;
+ option (complexopt6).xyzzy = 24;
+}
+
+// ------------------------------------------------------
+// Definitions for testing aggregate option parsing.
+// See descriptor_unittest.cc.
+
+message AggregateMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message AggregateMessageSetElement {
+ extend AggregateMessageSet {
+ optional AggregateMessageSetElement message_set_extension = 15447542;
+ }
+ optional string s = 1;
+}
+
+// A helper type used to test aggregate option parsing
+message Aggregate {
+ optional int32 i = 1;
+ optional string s = 2;
+
+ // A nested object
+ optional Aggregate sub = 3;
+
+ // To test the parsing of extensions inside aggregate values
+ optional google.protobuf.FileOptions file = 4;
+ extend google.protobuf.FileOptions {
+ optional Aggregate nested = 15476903;
+ }
+
+ // An embedded message set
+ optional AggregateMessageSet mset = 5;
+}
+
+// Allow Aggregate to be used as an option at all possible locations
+// in the .proto grammer.
+extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; }
+extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; }
+extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; }
+extend google.protobuf.EnumOptions { optional Aggregate enumopt = 15483218; }
+extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; }
+extend google.protobuf.ServiceOptions { optional Aggregate serviceopt = 15497145; }
+extend google.protobuf.MethodOptions { optional Aggregate methodopt = 15512713; }
+
+// Try using AggregateOption at different points in the proto grammar
+option (fileopt) = {
+ s: 'FileAnnotation'
+ // Also test the handling of comments
+ /* of both types */ i: 100
+
+ sub { s: 'NestedFileAnnotation' }
+
+ // Include a google.protobuf.FileOptions and recursively extend it with
+ // another fileopt.
+ file {
+ [protobuf_unittest.fileopt] {
+ s:'FileExtensionAnnotation'
+ }
+ }
+
+ // A message set inside an option value
+ mset {
+ [protobuf_unittest.AggregateMessageSetElement.message_set_extension] {
+ s: 'EmbeddedMessageSetElement'
+ }
+ }
+};
+
+message AggregateMessage {
+ option (msgopt) = { i:101 s:'MessageAnnotation' };
+ optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }];
+}
+
+service AggregateService {
+ option (serviceopt) = { s:'ServiceAnnotation' };
+ rpc Method (AggregateMessage) returns (AggregateMessage) {
+ option (methodopt) = { s:'MethodAnnotation' };
+ }
+}
+
+enum AggregateEnum {
+ option (enumopt) = { s:'EnumAnnotation' };
+ VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }];
+}
+
+// Test custom options for nested type.
+message NestedOptionType {
+ message NestedMessage {
+ option (message_opt1) = 1001;
+ optional int32 nested_field = 1 [(field_opt1) = 1002];
+ }
+ enum NestedEnum {
+ option (enum_opt1) = 1003;
+ NESTED_ENUM_VALUE = 1 [(enum_value_opt1) = 1004];
+ }
+ extend google.protobuf.FileOptions {
+ optional int32 nested_extension = 7912573 [(field_opt2) = 1005];
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
new file mode 100644
index 0000000000..fa1762594e
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_embed_optimize_for.proto
@@ -0,0 +1,50 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
+
+import "google/protobuf/unittest_optimize_for.proto";
+
+package protobuf_unittest;
+
+// We optimize for speed here, but we are importing a proto that is optimized
+// for code size.
+option optimize_for = SPEED;
+
+message TestEmbedOptimizedForSize {
+ // Test that embedding a message which has optimize_for = CODE_SIZE into
+ // one optimized for speed works.
+ optional TestOptimizedForSize optional_message = 1;
+ repeated TestOptimizedForSize repeated_message = 2;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto
new file mode 100644
index 0000000000..ab12d1fb9f
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_empty.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file intentionally left blank. (At one point this wouldn't compile
+// correctly.)
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
new file mode 100644
index 0000000000..bc0b7c16a0
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_enormous_descriptor.proto
@@ -0,0 +1,1046 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file that has an extremely large descriptor. Used to test that
+// descriptors over 64k don't break the string literal length limit in Java.
+
+
+package google.protobuf;
+option java_package = "com.google.protobuf";
+
+// Avoid generating insanely long methods.
+option optimize_for = CODE_SIZE;
+
+message TestEnormousDescriptor {
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1 = 1 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_2 = 2 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_3 = 3 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_4 = 4 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_5 = 5 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_6 = 6 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_7 = 7 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_8 = 8 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_9 = 9 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_10 = 10 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_11 = 11 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_12 = 12 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_13 = 13 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_14 = 14 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_15 = 15 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_16 = 16 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_17 = 17 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_18 = 18 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_19 = 19 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_20 = 20 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_21 = 21 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_22 = 22 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_23 = 23 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_24 = 24 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_25 = 25 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_26 = 26 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_27 = 27 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_28 = 28 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_29 = 29 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_30 = 30 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_31 = 31 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_32 = 32 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_33 = 33 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_34 = 34 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_35 = 35 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_36 = 36 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_37 = 37 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_38 = 38 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_39 = 39 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_40 = 40 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_41 = 41 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_42 = 42 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_43 = 43 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_44 = 44 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_45 = 45 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_46 = 46 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_47 = 47 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_48 = 48 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_49 = 49 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_50 = 50 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_51 = 51 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_52 = 52 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_53 = 53 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_54 = 54 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_55 = 55 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_56 = 56 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_57 = 57 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_58 = 58 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_59 = 59 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_60 = 60 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_61 = 61 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_62 = 62 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_63 = 63 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_64 = 64 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_65 = 65 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_66 = 66 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_67 = 67 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_68 = 68 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_69 = 69 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_70 = 70 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_71 = 71 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_72 = 72 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_73 = 73 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_74 = 74 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_75 = 75 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_76 = 76 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_77 = 77 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_78 = 78 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_79 = 79 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_80 = 80 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_81 = 81 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_82 = 82 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_83 = 83 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_84 = 84 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_85 = 85 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_86 = 86 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_87 = 87 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_88 = 88 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_89 = 89 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_90 = 90 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_91 = 91 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_92 = 92 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_93 = 93 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_94 = 94 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_95 = 95 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_96 = 96 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_97 = 97 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_98 = 98 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_99 = 99 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_100 = 100 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_101 = 101 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_102 = 102 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_103 = 103 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_104 = 104 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_105 = 105 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_106 = 106 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_107 = 107 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_108 = 108 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_109 = 109 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_110 = 110 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_111 = 111 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_112 = 112 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_113 = 113 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_114 = 114 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_115 = 115 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_116 = 116 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_117 = 117 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_118 = 118 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_119 = 119 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_120 = 120 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_121 = 121 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_122 = 122 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_123 = 123 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_124 = 124 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_125 = 125 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_126 = 126 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_127 = 127 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_128 = 128 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_129 = 129 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_130 = 130 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_131 = 131 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_132 = 132 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_133 = 133 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_134 = 134 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_135 = 135 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_136 = 136 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_137 = 137 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_138 = 138 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_139 = 139 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_140 = 140 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_141 = 141 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_142 = 142 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_143 = 143 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_144 = 144 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_145 = 145 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_146 = 146 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_147 = 147 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_148 = 148 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_149 = 149 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_150 = 150 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_151 = 151 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_152 = 152 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_153 = 153 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_154 = 154 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_155 = 155 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_156 = 156 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_157 = 157 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_158 = 158 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_159 = 159 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_160 = 160 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_161 = 161 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_162 = 162 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_163 = 163 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_164 = 164 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_165 = 165 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_166 = 166 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_167 = 167 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_168 = 168 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_169 = 169 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_170 = 170 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_171 = 171 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_172 = 172 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_173 = 173 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_174 = 174 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_175 = 175 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_176 = 176 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_177 = 177 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_178 = 178 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_179 = 179 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_180 = 180 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_181 = 181 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_182 = 182 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_183 = 183 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_184 = 184 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_185 = 185 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_186 = 186 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_187 = 187 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_188 = 188 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_189 = 189 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_190 = 190 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_191 = 191 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_192 = 192 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_193 = 193 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_194 = 194 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_195 = 195 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_196 = 196 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_197 = 197 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_198 = 198 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_199 = 199 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_200 = 200 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_201 = 201 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_202 = 202 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_203 = 203 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_204 = 204 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_205 = 205 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_206 = 206 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_207 = 207 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_208 = 208 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_209 = 209 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_210 = 210 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_211 = 211 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_212 = 212 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_213 = 213 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_214 = 214 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_215 = 215 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_216 = 216 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_217 = 217 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_218 = 218 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_219 = 219 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_220 = 220 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_221 = 221 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_222 = 222 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_223 = 223 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_224 = 224 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_225 = 225 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_226 = 226 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_227 = 227 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_228 = 228 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_229 = 229 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_230 = 230 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_231 = 231 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_232 = 232 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_233 = 233 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_234 = 234 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_235 = 235 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_236 = 236 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_237 = 237 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_238 = 238 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_239 = 239 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_240 = 240 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_241 = 241 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_242 = 242 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_243 = 243 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_244 = 244 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_245 = 245 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_246 = 246 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_247 = 247 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_248 = 248 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_249 = 249 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_250 = 250 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_251 = 251 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_252 = 252 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_253 = 253 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_254 = 254 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_255 = 255 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_256 = 256 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_257 = 257 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_258 = 258 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_259 = 259 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_260 = 260 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_261 = 261 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_262 = 262 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_263 = 263 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_264 = 264 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_265 = 265 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_266 = 266 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_267 = 267 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_268 = 268 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_269 = 269 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_270 = 270 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_271 = 271 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_272 = 272 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_273 = 273 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_274 = 274 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_275 = 275 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_276 = 276 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_277 = 277 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_278 = 278 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_279 = 279 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_280 = 280 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_281 = 281 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_282 = 282 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_283 = 283 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_284 = 284 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_285 = 285 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_286 = 286 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_287 = 287 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_288 = 288 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_289 = 289 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_290 = 290 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_291 = 291 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_292 = 292 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_293 = 293 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_294 = 294 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_295 = 295 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_296 = 296 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_297 = 297 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_298 = 298 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_299 = 299 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_300 = 300 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_301 = 301 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_302 = 302 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_303 = 303 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_304 = 304 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_305 = 305 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_306 = 306 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_307 = 307 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_308 = 308 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_309 = 309 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_310 = 310 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_311 = 311 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_312 = 312 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_313 = 313 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_314 = 314 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_315 = 315 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_316 = 316 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_317 = 317 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_318 = 318 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_319 = 319 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_320 = 320 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_321 = 321 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_322 = 322 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_323 = 323 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_324 = 324 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_325 = 325 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_326 = 326 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_327 = 327 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_328 = 328 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_329 = 329 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_330 = 330 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_331 = 331 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_332 = 332 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_333 = 333 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_334 = 334 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_335 = 335 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_336 = 336 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_337 = 337 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_338 = 338 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_339 = 339 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_340 = 340 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_341 = 341 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_342 = 342 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_343 = 343 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_344 = 344 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_345 = 345 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_346 = 346 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_347 = 347 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_348 = 348 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_349 = 349 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_350 = 350 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_351 = 351 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_352 = 352 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_353 = 353 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_354 = 354 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_355 = 355 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_356 = 356 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_357 = 357 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_358 = 358 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_359 = 359 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_360 = 360 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_361 = 361 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_362 = 362 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_363 = 363 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_364 = 364 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_365 = 365 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_366 = 366 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_367 = 367 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_368 = 368 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_369 = 369 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_370 = 370 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_371 = 371 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_372 = 372 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_373 = 373 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_374 = 374 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_375 = 375 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_376 = 376 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_377 = 377 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_378 = 378 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_379 = 379 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_380 = 380 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_381 = 381 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_382 = 382 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_383 = 383 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_384 = 384 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_385 = 385 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_386 = 386 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_387 = 387 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_388 = 388 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_389 = 389 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_390 = 390 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_391 = 391 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_392 = 392 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_393 = 393 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_394 = 394 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_395 = 395 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_396 = 396 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_397 = 397 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_398 = 398 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_399 = 399 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_400 = 400 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_401 = 401 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_402 = 402 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_403 = 403 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_404 = 404 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_405 = 405 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_406 = 406 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_407 = 407 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_408 = 408 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_409 = 409 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_410 = 410 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_411 = 411 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_412 = 412 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_413 = 413 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_414 = 414 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_415 = 415 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_416 = 416 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_417 = 417 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_418 = 418 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_419 = 419 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_420 = 420 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_421 = 421 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_422 = 422 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_423 = 423 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_424 = 424 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_425 = 425 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_426 = 426 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_427 = 427 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_428 = 428 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_429 = 429 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_430 = 430 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_431 = 431 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_432 = 432 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_433 = 433 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_434 = 434 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_435 = 435 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_436 = 436 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_437 = 437 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_438 = 438 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_439 = 439 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_440 = 440 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_441 = 441 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_442 = 442 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_443 = 443 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_444 = 444 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_445 = 445 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_446 = 446 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_447 = 447 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_448 = 448 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_449 = 449 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_450 = 450 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_451 = 451 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_452 = 452 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_453 = 453 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_454 = 454 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_455 = 455 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_456 = 456 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_457 = 457 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_458 = 458 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_459 = 459 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_460 = 460 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_461 = 461 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_462 = 462 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_463 = 463 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_464 = 464 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_465 = 465 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_466 = 466 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_467 = 467 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_468 = 468 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_469 = 469 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_470 = 470 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_471 = 471 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_472 = 472 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_473 = 473 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_474 = 474 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_475 = 475 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_476 = 476 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_477 = 477 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_478 = 478 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_479 = 479 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_480 = 480 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_481 = 481 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_482 = 482 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_483 = 483 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_484 = 484 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_485 = 485 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_486 = 486 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_487 = 487 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_488 = 488 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_489 = 489 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_490 = 490 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_491 = 491 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_492 = 492 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_493 = 493 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_494 = 494 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_495 = 495 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_496 = 496 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_497 = 497 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_498 = 498 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_499 = 499 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_500 = 500 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_501 = 501 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_502 = 502 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_503 = 503 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_504 = 504 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_505 = 505 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_506 = 506 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_507 = 507 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_508 = 508 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_509 = 509 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_510 = 510 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_511 = 511 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_512 = 512 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_513 = 513 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_514 = 514 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_515 = 515 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_516 = 516 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_517 = 517 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_518 = 518 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_519 = 519 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_520 = 520 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_521 = 521 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_522 = 522 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_523 = 523 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_524 = 524 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_525 = 525 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_526 = 526 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_527 = 527 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_528 = 528 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_529 = 529 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_530 = 530 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_531 = 531 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_532 = 532 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_533 = 533 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_534 = 534 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_535 = 535 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_536 = 536 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_537 = 537 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_538 = 538 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_539 = 539 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_540 = 540 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_541 = 541 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_542 = 542 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_543 = 543 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_544 = 544 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_545 = 545 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_546 = 546 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_547 = 547 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_548 = 548 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_549 = 549 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_550 = 550 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_551 = 551 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_552 = 552 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_553 = 553 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_554 = 554 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_555 = 555 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_556 = 556 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_557 = 557 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_558 = 558 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_559 = 559 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_560 = 560 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_561 = 561 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_562 = 562 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_563 = 563 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_564 = 564 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_565 = 565 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_566 = 566 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_567 = 567 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_568 = 568 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_569 = 569 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_570 = 570 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_571 = 571 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_572 = 572 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_573 = 573 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_574 = 574 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_575 = 575 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_576 = 576 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_577 = 577 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_578 = 578 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_579 = 579 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_580 = 580 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_581 = 581 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_582 = 582 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_583 = 583 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_584 = 584 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_585 = 585 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_586 = 586 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_587 = 587 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_588 = 588 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_589 = 589 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_590 = 590 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_591 = 591 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_592 = 592 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_593 = 593 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_594 = 594 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_595 = 595 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_596 = 596 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_597 = 597 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_598 = 598 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_599 = 599 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_600 = 600 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_601 = 601 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_602 = 602 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_603 = 603 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_604 = 604 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_605 = 605 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_606 = 606 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_607 = 607 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_608 = 608 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_609 = 609 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_610 = 610 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_611 = 611 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_612 = 612 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_613 = 613 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_614 = 614 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_615 = 615 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_616 = 616 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_617 = 617 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_618 = 618 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_619 = 619 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_620 = 620 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_621 = 621 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_622 = 622 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_623 = 623 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_624 = 624 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_625 = 625 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_626 = 626 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_627 = 627 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_628 = 628 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_629 = 629 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_630 = 630 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_631 = 631 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_632 = 632 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_633 = 633 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_634 = 634 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_635 = 635 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_636 = 636 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_637 = 637 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_638 = 638 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_639 = 639 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_640 = 640 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_641 = 641 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_642 = 642 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_643 = 643 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_644 = 644 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_645 = 645 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_646 = 646 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_647 = 647 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_648 = 648 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_649 = 649 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_650 = 650 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_651 = 651 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_652 = 652 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_653 = 653 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_654 = 654 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_655 = 655 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_656 = 656 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_657 = 657 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_658 = 658 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_659 = 659 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_660 = 660 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_661 = 661 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_662 = 662 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_663 = 663 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_664 = 664 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_665 = 665 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_666 = 666 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_667 = 667 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_668 = 668 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_669 = 669 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_670 = 670 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_671 = 671 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_672 = 672 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_673 = 673 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_674 = 674 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_675 = 675 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_676 = 676 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_677 = 677 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_678 = 678 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_679 = 679 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_680 = 680 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_681 = 681 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_682 = 682 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_683 = 683 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_684 = 684 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_685 = 685 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_686 = 686 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_687 = 687 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_688 = 688 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_689 = 689 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_690 = 690 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_691 = 691 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_692 = 692 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_693 = 693 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_694 = 694 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_695 = 695 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_696 = 696 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_697 = 697 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_698 = 698 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_699 = 699 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_700 = 700 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_701 = 701 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_702 = 702 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_703 = 703 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_704 = 704 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_705 = 705 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_706 = 706 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_707 = 707 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_708 = 708 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_709 = 709 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_710 = 710 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_711 = 711 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_712 = 712 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_713 = 713 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_714 = 714 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_715 = 715 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_716 = 716 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_717 = 717 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_718 = 718 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_719 = 719 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_720 = 720 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_721 = 721 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_722 = 722 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_723 = 723 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_724 = 724 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_725 = 725 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_726 = 726 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_727 = 727 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_728 = 728 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_729 = 729 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_730 = 730 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_731 = 731 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_732 = 732 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_733 = 733 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_734 = 734 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_735 = 735 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_736 = 736 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_737 = 737 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_738 = 738 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_739 = 739 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_740 = 740 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_741 = 741 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_742 = 742 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_743 = 743 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_744 = 744 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_745 = 745 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_746 = 746 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_747 = 747 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_748 = 748 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_749 = 749 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_750 = 750 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_751 = 751 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_752 = 752 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_753 = 753 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_754 = 754 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_755 = 755 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_756 = 756 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_757 = 757 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_758 = 758 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_759 = 759 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_760 = 760 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_761 = 761 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_762 = 762 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_763 = 763 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_764 = 764 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_765 = 765 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_766 = 766 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_767 = 767 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_768 = 768 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_769 = 769 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_770 = 770 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_771 = 771 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_772 = 772 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_773 = 773 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_774 = 774 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_775 = 775 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_776 = 776 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_777 = 777 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_778 = 778 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_779 = 779 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_780 = 780 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_781 = 781 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_782 = 782 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_783 = 783 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_784 = 784 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_785 = 785 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_786 = 786 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_787 = 787 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_788 = 788 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_789 = 789 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_790 = 790 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_791 = 791 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_792 = 792 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_793 = 793 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_794 = 794 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_795 = 795 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_796 = 796 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_797 = 797 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_798 = 798 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_799 = 799 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_800 = 800 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_801 = 801 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_802 = 802 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_803 = 803 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_804 = 804 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_805 = 805 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_806 = 806 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_807 = 807 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_808 = 808 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_809 = 809 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_810 = 810 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_811 = 811 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_812 = 812 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_813 = 813 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_814 = 814 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_815 = 815 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_816 = 816 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_817 = 817 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_818 = 818 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_819 = 819 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_820 = 820 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_821 = 821 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_822 = 822 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_823 = 823 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_824 = 824 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_825 = 825 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_826 = 826 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_827 = 827 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_828 = 828 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_829 = 829 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_830 = 830 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_831 = 831 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_832 = 832 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_833 = 833 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_834 = 834 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_835 = 835 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_836 = 836 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_837 = 837 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_838 = 838 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_839 = 839 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_840 = 840 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_841 = 841 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_842 = 842 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_843 = 843 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_844 = 844 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_845 = 845 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_846 = 846 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_847 = 847 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_848 = 848 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_849 = 849 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_850 = 850 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_851 = 851 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_852 = 852 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_853 = 853 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_854 = 854 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_855 = 855 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_856 = 856 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_857 = 857 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_858 = 858 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_859 = 859 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_860 = 860 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_861 = 861 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_862 = 862 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_863 = 863 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_864 = 864 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_865 = 865 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_866 = 866 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_867 = 867 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_868 = 868 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_869 = 869 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_870 = 870 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_871 = 871 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_872 = 872 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_873 = 873 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_874 = 874 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_875 = 875 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_876 = 876 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_877 = 877 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_878 = 878 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_879 = 879 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_880 = 880 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_881 = 881 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_882 = 882 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_883 = 883 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_884 = 884 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_885 = 885 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_886 = 886 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_887 = 887 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_888 = 888 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_889 = 889 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_890 = 890 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_891 = 891 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_892 = 892 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_893 = 893 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_894 = 894 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_895 = 895 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_896 = 896 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_897 = 897 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_898 = 898 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_899 = 899 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_900 = 900 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_901 = 901 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_902 = 902 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_903 = 903 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_904 = 904 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_905 = 905 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_906 = 906 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_907 = 907 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_908 = 908 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_909 = 909 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_910 = 910 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_911 = 911 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_912 = 912 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_913 = 913 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_914 = 914 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_915 = 915 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_916 = 916 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_917 = 917 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_918 = 918 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_919 = 919 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_920 = 920 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_921 = 921 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_922 = 922 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_923 = 923 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_924 = 924 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_925 = 925 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_926 = 926 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_927 = 927 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_928 = 928 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_929 = 929 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_930 = 930 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_931 = 931 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_932 = 932 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_933 = 933 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_934 = 934 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_935 = 935 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_936 = 936 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_937 = 937 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_938 = 938 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_939 = 939 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_940 = 940 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_941 = 941 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_942 = 942 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_943 = 943 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_944 = 944 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_945 = 945 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_946 = 946 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_947 = 947 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_948 = 948 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_949 = 949 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_950 = 950 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_951 = 951 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_952 = 952 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_953 = 953 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_954 = 954 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_955 = 955 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_956 = 956 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_957 = 957 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_958 = 958 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_959 = 959 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_960 = 960 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_961 = 961 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_962 = 962 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_963 = 963 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_964 = 964 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_965 = 965 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_966 = 966 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_967 = 967 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_968 = 968 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_969 = 969 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_970 = 970 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_971 = 971 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_972 = 972 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_973 = 973 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_974 = 974 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_975 = 975 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_976 = 976 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_977 = 977 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_978 = 978 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_979 = 979 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_980 = 980 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_981 = 981 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_982 = 982 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_983 = 983 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_984 = 984 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_985 = 985 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_986 = 986 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_987 = 987 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_988 = 988 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_989 = 989 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_990 = 990 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_991 = 991 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_992 = 992 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_993 = 993 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_994 = 994 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_995 = 995 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_996 = 996 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_997 = 997 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_998 = 998 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_999 = 999 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+ optional string long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000 = 1000 [default="long default value is also loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong"];
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
new file mode 100644
index 0000000000..c115b11171
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import.proto
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which is imported by unittest.proto to test importing.
+
+
+// We don't put this in a package within proto2 because we need to make sure
+// that the generated code doesn't depend on being in the proto2 namespace.
+// In test_util.h we do
+// "using namespace unittest_import = protobuf_unittest_import".
+package protobuf_unittest_import;
+
+option optimize_for = SPEED;
+
+// Excercise the java_package option.
+option java_package = "com.google.protobuf.test";
+
+// Do not set a java_outer_classname here to verify that Proto2 works without
+// one.
+
+// Test public import
+import public "google/protobuf/unittest_import_public.proto";
+
+message ImportMessage {
+ optional int32 d = 1;
+}
+
+enum ImportEnum {
+ IMPORT_FOO = 7;
+ IMPORT_BAR = 8;
+ IMPORT_BAZ = 9;
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto
new file mode 100644
index 0000000000..81b117fe84
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_lite.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+import public "google/protobuf/unittest_import_public_lite.proto";
+
+message ImportMessageLite {
+ optional int32 d = 1;
+}
+
+enum ImportEnumLite {
+ IMPORT_LITE_FOO = 7;
+ IMPORT_LITE_BAR = 8;
+ IMPORT_LITE_BAZ = 9;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000000..ea5d1b13fe
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option java_package = "com.google.protobuf.test";
+
+message PublicImportMessage {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000000..d077563cbd
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_import_public_lite.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: liujisi@google.com (Pherl Liu)
+
+
+package protobuf_unittest_import;
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+message PublicImportMessageLite {
+ optional int32 e = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto
new file mode 100644
index 0000000000..a1764aac8d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite.proto
@@ -0,0 +1,360 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is like unittest.proto but with optimize_for = LITE_RUNTIME.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest_import_lite.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+option java_package = "com.google.protobuf";
+
+// Same as TestAllTypes but with the lite runtime.
+message TestAllTypesLite {
+ message NestedMessage {
+ optional int32 bb = 1;
+ }
+
+ enum NestedEnum {
+ FOO = 1;
+ BAR = 2;
+ BAZ = 3;
+ }
+
+ // Singular
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+
+ optional NestedMessage optional_nested_message = 18;
+ optional ForeignMessageLite optional_foreign_message = 19;
+ optional protobuf_unittest_import.ImportMessageLite
+ optional_import_message = 20;
+
+ optional NestedEnum optional_nested_enum = 21;
+ optional ForeignEnumLite optional_foreign_enum = 22;
+ optional protobuf_unittest_import.ImportEnumLite optional_import_enum = 23;
+
+ optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+ optional string optional_cord = 25 [ctype=CORD];
+
+ // Defined in unittest_import_public.proto
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message = 26;
+
+ optional NestedMessage optional_lazy_message = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated ForeignMessageLite repeated_foreign_message = 49;
+ repeated protobuf_unittest_import.ImportMessageLite
+ repeated_import_message = 50;
+
+ repeated NestedEnum repeated_nested_enum = 51;
+ repeated ForeignEnumLite repeated_foreign_enum = 52;
+ repeated protobuf_unittest_import.ImportEnumLite repeated_import_enum = 53;
+
+ repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+ repeated string repeated_cord = 55 [ctype=CORD];
+
+ repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32 = 61 [default = 41 ];
+ optional int64 default_int64 = 62 [default = 42 ];
+ optional uint32 default_uint32 = 63 [default = 43 ];
+ optional uint64 default_uint64 = 64 [default = 44 ];
+ optional sint32 default_sint32 = 65 [default = -45 ];
+ optional sint64 default_sint64 = 66 [default = 46 ];
+ optional fixed32 default_fixed32 = 67 [default = 47 ];
+ optional fixed64 default_fixed64 = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32 = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64 = 70 [default = -50 ];
+ optional float default_float = 71 [default = 51.5 ];
+ optional double default_double = 72 [default = 52e3 ];
+ optional bool default_bool = 73 [default = true ];
+ optional string default_string = 74 [default = "hello"];
+ optional bytes default_bytes = 75 [default = "world"];
+
+ optional NestedEnum default_nested_enum = 81 [default = BAR];
+ optional ForeignEnumLite default_foreign_enum = 82
+ [default = FOREIGN_LITE_BAR];
+ optional protobuf_unittest_import.ImportEnumLite
+ default_import_enum = 83 [default = IMPORT_LITE_BAR];
+
+ optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"];
+ optional string default_cord = 85 [ctype=CORD,default="123"];
+}
+
+message ForeignMessageLite {
+ optional int32 c = 1;
+}
+
+enum ForeignEnumLite {
+ FOREIGN_LITE_FOO = 4;
+ FOREIGN_LITE_BAR = 5;
+ FOREIGN_LITE_BAZ = 6;
+}
+
+message TestPackedTypesLite {
+ repeated int32 packed_int32 = 90 [packed = true];
+ repeated int64 packed_int64 = 91 [packed = true];
+ repeated uint32 packed_uint32 = 92 [packed = true];
+ repeated uint64 packed_uint64 = 93 [packed = true];
+ repeated sint32 packed_sint32 = 94 [packed = true];
+ repeated sint64 packed_sint64 = 95 [packed = true];
+ repeated fixed32 packed_fixed32 = 96 [packed = true];
+ repeated fixed64 packed_fixed64 = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32 = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64 = 99 [packed = true];
+ repeated float packed_float = 100 [packed = true];
+ repeated double packed_double = 101 [packed = true];
+ repeated bool packed_bool = 102 [packed = true];
+ repeated ForeignEnumLite packed_enum = 103 [packed = true];
+}
+
+message TestAllExtensionsLite {
+ extensions 1 to max;
+}
+
+extend TestAllExtensionsLite {
+ // Singular
+ optional int32 optional_int32_extension_lite = 1;
+ optional int64 optional_int64_extension_lite = 2;
+ optional uint32 optional_uint32_extension_lite = 3;
+ optional uint64 optional_uint64_extension_lite = 4;
+ optional sint32 optional_sint32_extension_lite = 5;
+ optional sint64 optional_sint64_extension_lite = 6;
+ optional fixed32 optional_fixed32_extension_lite = 7;
+ optional fixed64 optional_fixed64_extension_lite = 8;
+ optional sfixed32 optional_sfixed32_extension_lite = 9;
+ optional sfixed64 optional_sfixed64_extension_lite = 10;
+ optional float optional_float_extension_lite = 11;
+ optional double optional_double_extension_lite = 12;
+ optional bool optional_bool_extension_lite = 13;
+ optional string optional_string_extension_lite = 14;
+ optional bytes optional_bytes_extension_lite = 15;
+
+ optional group OptionalGroup_extension_lite = 16 {
+ optional int32 a = 17;
+ }
+
+ optional TestAllTypesLite.NestedMessage optional_nested_message_extension_lite
+ = 18;
+ optional ForeignMessageLite optional_foreign_message_extension_lite = 19;
+ optional protobuf_unittest_import.ImportMessageLite
+ optional_import_message_extension_lite = 20;
+
+ optional TestAllTypesLite.NestedEnum optional_nested_enum_extension_lite = 21;
+ optional ForeignEnumLite optional_foreign_enum_extension_lite = 22;
+ optional protobuf_unittest_import.ImportEnumLite
+ optional_import_enum_extension_lite = 23;
+
+ optional string optional_string_piece_extension_lite = 24
+ [ctype=STRING_PIECE];
+ optional string optional_cord_extension_lite = 25 [ctype=CORD];
+
+ optional protobuf_unittest_import.PublicImportMessageLite
+ optional_public_import_message_extension_lite = 26;
+
+ optional TestAllTypesLite.NestedMessage
+ optional_lazy_message_extension_lite = 27 [lazy=true];
+
+ // Repeated
+ repeated int32 repeated_int32_extension_lite = 31;
+ repeated int64 repeated_int64_extension_lite = 32;
+ repeated uint32 repeated_uint32_extension_lite = 33;
+ repeated uint64 repeated_uint64_extension_lite = 34;
+ repeated sint32 repeated_sint32_extension_lite = 35;
+ repeated sint64 repeated_sint64_extension_lite = 36;
+ repeated fixed32 repeated_fixed32_extension_lite = 37;
+ repeated fixed64 repeated_fixed64_extension_lite = 38;
+ repeated sfixed32 repeated_sfixed32_extension_lite = 39;
+ repeated sfixed64 repeated_sfixed64_extension_lite = 40;
+ repeated float repeated_float_extension_lite = 41;
+ repeated double repeated_double_extension_lite = 42;
+ repeated bool repeated_bool_extension_lite = 43;
+ repeated string repeated_string_extension_lite = 44;
+ repeated bytes repeated_bytes_extension_lite = 45;
+
+ repeated group RepeatedGroup_extension_lite = 46 {
+ optional int32 a = 47;
+ }
+
+ repeated TestAllTypesLite.NestedMessage repeated_nested_message_extension_lite
+ = 48;
+ repeated ForeignMessageLite repeated_foreign_message_extension_lite = 49;
+ repeated protobuf_unittest_import.ImportMessageLite
+ repeated_import_message_extension_lite = 50;
+
+ repeated TestAllTypesLite.NestedEnum repeated_nested_enum_extension_lite = 51;
+ repeated ForeignEnumLite repeated_foreign_enum_extension_lite = 52;
+ repeated protobuf_unittest_import.ImportEnumLite
+ repeated_import_enum_extension_lite = 53;
+
+ repeated string repeated_string_piece_extension_lite = 54
+ [ctype=STRING_PIECE];
+ repeated string repeated_cord_extension_lite = 55 [ctype=CORD];
+
+ repeated TestAllTypesLite.NestedMessage
+ repeated_lazy_message_extension_lite = 57 [lazy=true];
+
+ // Singular with defaults
+ optional int32 default_int32_extension_lite = 61 [default = 41 ];
+ optional int64 default_int64_extension_lite = 62 [default = 42 ];
+ optional uint32 default_uint32_extension_lite = 63 [default = 43 ];
+ optional uint64 default_uint64_extension_lite = 64 [default = 44 ];
+ optional sint32 default_sint32_extension_lite = 65 [default = -45 ];
+ optional sint64 default_sint64_extension_lite = 66 [default = 46 ];
+ optional fixed32 default_fixed32_extension_lite = 67 [default = 47 ];
+ optional fixed64 default_fixed64_extension_lite = 68 [default = 48 ];
+ optional sfixed32 default_sfixed32_extension_lite = 69 [default = 49 ];
+ optional sfixed64 default_sfixed64_extension_lite = 70 [default = -50 ];
+ optional float default_float_extension_lite = 71 [default = 51.5 ];
+ optional double default_double_extension_lite = 72 [default = 52e3 ];
+ optional bool default_bool_extension_lite = 73 [default = true ];
+ optional string default_string_extension_lite = 74 [default = "hello"];
+ optional bytes default_bytes_extension_lite = 75 [default = "world"];
+
+ optional TestAllTypesLite.NestedEnum
+ default_nested_enum_extension_lite = 81 [default = BAR];
+ optional ForeignEnumLite
+ default_foreign_enum_extension_lite = 82 [default = FOREIGN_LITE_BAR];
+ optional protobuf_unittest_import.ImportEnumLite
+ default_import_enum_extension_lite = 83 [default = IMPORT_LITE_BAR];
+
+ optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE,
+ default="abc"];
+ optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"];
+}
+
+message TestPackedExtensionsLite {
+ extensions 1 to max;
+}
+
+extend TestPackedExtensionsLite {
+ repeated int32 packed_int32_extension_lite = 90 [packed = true];
+ repeated int64 packed_int64_extension_lite = 91 [packed = true];
+ repeated uint32 packed_uint32_extension_lite = 92 [packed = true];
+ repeated uint64 packed_uint64_extension_lite = 93 [packed = true];
+ repeated sint32 packed_sint32_extension_lite = 94 [packed = true];
+ repeated sint64 packed_sint64_extension_lite = 95 [packed = true];
+ repeated fixed32 packed_fixed32_extension_lite = 96 [packed = true];
+ repeated fixed64 packed_fixed64_extension_lite = 97 [packed = true];
+ repeated sfixed32 packed_sfixed32_extension_lite = 98 [packed = true];
+ repeated sfixed64 packed_sfixed64_extension_lite = 99 [packed = true];
+ repeated float packed_float_extension_lite = 100 [packed = true];
+ repeated double packed_double_extension_lite = 101 [packed = true];
+ repeated bool packed_bool_extension_lite = 102 [packed = true];
+ repeated ForeignEnumLite packed_enum_extension_lite = 103 [packed = true];
+}
+
+message TestNestedExtensionLite {
+ extend TestAllExtensionsLite {
+ optional int32 nested_extension = 12345;
+ }
+}
+
+// Test that deprecated fields work. We only verify that they compile (at one
+// point this failed).
+message TestDeprecatedLite {
+ optional int32 deprecated_field = 1 [deprecated = true];
+}
+
+// See the comments of the same type in unittest.proto.
+message TestParsingMergeLite {
+ message RepeatedFieldsGenerator {
+ repeated TestAllTypesLite field1 = 1;
+ repeated TestAllTypesLite field2 = 2;
+ repeated TestAllTypesLite field3 = 3;
+ repeated group Group1 = 10 {
+ optional TestAllTypesLite field1 = 11;
+ }
+ repeated group Group2 = 20 {
+ optional TestAllTypesLite field1 = 21;
+ }
+ repeated TestAllTypesLite ext1 = 1000;
+ repeated TestAllTypesLite ext2 = 1001;
+ }
+ required TestAllTypesLite required_all_types = 1;
+ optional TestAllTypesLite optional_all_types = 2;
+ repeated TestAllTypesLite repeated_all_types = 3;
+ optional group OptionalGroup = 10 {
+ optional TestAllTypesLite optional_group_all_types = 11;
+ }
+ repeated group RepeatedGroup = 20 {
+ optional TestAllTypesLite repeated_group_all_types = 21;
+ }
+ extensions 1000 to max;
+ extend TestParsingMergeLite {
+ optional TestAllTypesLite optional_ext = 1000;
+ repeated TestAllTypesLite repeated_ext = 1001;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
new file mode 100644
index 0000000000..d52cb8cc36
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -0,0 +1,43 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// Tests that a "lite" message can import a regular message.
+
+package protobuf_unittest;
+
+import "google/protobuf/unittest.proto";
+
+option optimize_for = LITE_RUNTIME;
+
+message TestLiteImportsNonlite {
+ optional TestAllTypes message = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
new file mode 100644
index 0000000000..3497f09fa6
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_mset.proto
@@ -0,0 +1,72 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// This file contains messages for testing message_set_wire_format.
+
+package protobuf_unittest;
+
+option optimize_for = SPEED;
+
+// A message with message_set_wire_format.
+message TestMessageSet {
+ option message_set_wire_format = true;
+ extensions 4 to max;
+}
+
+message TestMessageSetContainer {
+ optional TestMessageSet message_set = 1;
+}
+
+message TestMessageSetExtension1 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension1 message_set_extension = 1545008;
+ }
+ optional int32 i = 15;
+}
+
+message TestMessageSetExtension2 {
+ extend TestMessageSet {
+ optional TestMessageSetExtension2 message_set_extension = 1547769;
+ }
+ optional string str = 25;
+}
+
+// MessageSet wire format is equivalent to this.
+message RawMessageSet {
+ repeated group Item = 1 {
+ required int32 type_id = 2;
+ required bytes message = 3;
+ }
+}
+
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
new file mode 100644
index 0000000000..cffb4122c5
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_no_generic_services.proto
@@ -0,0 +1,52 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+
+package google.protobuf.no_generic_services_test;
+
+// *_generic_services are false by default.
+
+message TestMessage {
+ optional int32 a = 1;
+ extensions 1000 to max;
+}
+
+enum TestEnum {
+ FOO = 1;
+}
+
+extend TestMessage {
+ optional int32 test_extension = 1000;
+}
+
+service TestService {
+ rpc Foo(TestMessage) returns(TestMessage);
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto
new file mode 100644
index 0000000000..feecbef8d4
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/protos/src/proto/google/protobuf/unittest_optimize_for.proto
@@ -0,0 +1,61 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+// Based on original Protocol Buffers design by
+// Sanjay Ghemawat, Jeff Dean, and others.
+//
+// A proto file which uses optimize_for = CODE_SIZE.
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+option optimize_for = CODE_SIZE;
+
+message TestOptimizedForSize {
+ optional int32 i = 1;
+ optional ForeignMessage msg = 19;
+
+ extensions 1000 to max;
+
+ extend TestOptimizedForSize {
+ optional int32 test_extension = 1234;
+ optional TestRequiredOptimizedForSize test_extension2 = 1235;
+ }
+}
+
+message TestRequiredOptimizedForSize {
+ required int32 x = 1;
+}
+
+message TestOptionalOptimizedForSize {
+ optional TestRequiredOptimizedForSize o = 1;
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/test.sh b/third_party/protobuf/java/compatibility_tests/v2.5.0/test.sh
new file mode 100755
index 0000000000..5d5e9ed439
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/test.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+
+set -ex
+
+# Change to the script's directory.
+cd $(dirname $0)
+
+# Version of the tests (i.e., the version of protobuf from where we extracted
+# these tests).
+TEST_VERSION=`grep "^ <version>.*</version>" pom.xml | sed "s| <version>\(.*\)</version>|\1|"`
+
+# The old version of protobuf that we are testing compatibility against. This
+# is usually the same as TEST_VERSION (i.e., we use the tests extracted from
+# that version to test compatibility of the newest runtime against it), but it
+# is also possible to use this same test set to test the compatibiilty of the
+# latest version against other versions.
+case "$1" in
+ ""|2.5.0)
+ OLD_VERSION=2.5.0
+ OLD_VERSION_PROTOC=https://github.com/xfxyjwf/protobuf-compiler-release/raw/master/v2.5.0/linux/protoc
+ ;;
+ 2.6.1)
+ OLD_VERSION=2.6.1
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/2.6.1-build2/protoc-2.6.1-build2-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-1)
+ OLD_VERSION=3.0.0-beta-1
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-1/protoc-3.0.0-beta-1-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-2)
+ OLD_VERSION=3.0.0-beta-2
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-2/protoc-3.0.0-beta-2-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-3)
+ OLD_VERSION=3.0.0-beta-3
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-3/protoc-3.0.0-beta-3-linux-x86_64.exe
+ ;;
+ 3.0.0-beta-4)
+ OLD_VERSION=3.0.0-beta-4
+ OLD_VERSION_PROTOC=http://repo1.maven.org/maven2/com/google/protobuf/protoc/3.0.0-beta-4/protoc-3.0.0-beta-4-linux-x86_64.exe
+ ;;
+ *)
+ echo "[ERROR]: Unknown version number: $1"
+ exit 1
+ ;;
+esac
+
+# Extract the latest protobuf version number.
+VERSION_NUMBER=`grep "^ <version>.*</version>" ../../pom.xml | sed "s| <version>\(.*\)</version>|\1|"`
+
+echo "Running compatibility tests between $VERSION_NUMBER and $OLD_VERSION"
+
+# Check protoc
+[ -f ../../../src/protoc ] || {
+ echo "[ERROR]: Please build protoc first."
+ exit 1
+}
+
+# Build and install protobuf-java-$VERSION_NUMBER.jar
+[ -f ../../core/target/protobuf-java-$VERSION_NUMBER.jar ] || {
+ pushd ../..
+ mvn install -Dmaven.test.skip=true
+ popd
+}
+
+# Download old version source for the compatibility test
+[ -d protobuf ] || {
+ git clone https://github.com/google/protobuf.git
+ cd protobuf
+ git reset --hard v$TEST_VERSION
+ cd ..
+}
+
+# Download old version protoc compiler (for linux)
+wget $OLD_VERSION_PROTOC -O protoc
+chmod +x protoc
+
+# Test source compatibility. In these tests we recompile everything against
+# the new runtime (including old version generated code).
+
+# Test A.1:
+# protos: use new version
+# more_protos: use old version
+mvn clean test \
+ -Dprotobuf.test.source.path=$(pwd)/protobuf \
+ -Dprotoc.path=$(pwd)/protoc \
+ -Dprotos.protoc.path=$(pwd)/../../../src/protoc \
+ -Dprotobuf.version=$VERSION_NUMBER
+
+# Test A.2:
+# protos: use old version
+# more_protos: use new version
+mvn clean test \
+ -Dprotobuf.test.source.path=$(pwd)/protobuf \
+ -Dprotoc.path=$(pwd)/protoc \
+ -Dmore_protos.protoc.path=$(pwd)/../../../src/protoc \
+ -Dprotobuf.version=$VERSION_NUMBER
+
+# Test binary compatibility. In these tests we run the old version compiled
+# jar against the new runtime directly without recompile.
+
+# Collect all test dependencies in a single jar file (except for protobuf) to
+# make it easier to run binary compatibility test (where we will need to run
+# the jar files directly).
+cd deps
+mvn assembly:single
+cd ..
+cp -f deps/target/compatibility-test-deps-${TEST_VERSION}-jar-with-dependencies.jar deps.jar
+
+# Build the old version of all 3 artifacts.
+mvn clean install -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/protoc -Dprotobuf.version=$OLD_VERSION
+cp -f protos/target/compatibility-protos-${TEST_VERSION}.jar protos.jar
+cp -f more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar more_protos.jar
+cp -f tests/target/compatibility-tests-${TEST_VERSION}.jar tests.jar
+
+# Collect the list of tests we need to run.
+TESTS=`find tests -name "*Test.java" | sed "s|/|.|g;s/.java$//g;s/tests.src.main.java.//g"`
+
+# Test B.1: run all the old artifacts against the new runtime. Note that we
+# must run the test in the protobuf source tree because some of the tests need
+# to read golden test data files.
+cd protobuf
+java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos.jar:../more_protos.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
+cd ..
+
+# Test B.2: update protos.jar only.
+cd protos
+mvn clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER
+cd ..
+cd protobuf
+java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos/target/compatibility-protos-${TEST_VERSION}.jar:../more_protos.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
+cd ..
+
+# Test B.3: update more_protos.jar only.
+cd more_protos
+mvn clean package -Dmaven.test.skip=true -Dprotoc.path=$(pwd)/../../../../src/protoc -Dprotobuf.version=$VERSION_NUMBER
+cd ..
+cd protobuf
+java -cp ../../../core/target/protobuf-java-$VERSION_NUMBER.jar:../protos.jar:../more_protos/target/compatibility-more-protos-${TEST_VERSION}.jar:../tests.jar:../deps.jar org.junit.runner.JUnitCore $TESTS
+cd ..
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/pom.xml b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/pom.xml
new file mode 100644
index 0000000000..f1ce46e7ab
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-test-suite</artifactId>
+ <version>2.5.0</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-tests</artifactId>
+ <version>2.5.0</version>
+
+ <name>Compatibility Tests</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>${tests.protobuf.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-protos</artifactId>
+ <version>2.5.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf.compatibility</groupId>
+ <artifactId>compatibility-more-protos</artifactId>
+ <version>2.5.0</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <testSourceDirectory>${basedir}/src/main/java/</testSourceDirectory>
+ <testClassesDirectory>${project.build.directory}/classes/</testClassesDirectory>
+ <includes>
+ <include>**/*Test.java</include>
+ </includes>
+ <workingDirectory>${protobuf.test.source.path}</workingDirectory>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java
new file mode 100644
index 0000000000..6789550c49
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/AbstractMessageTest.java
@@ -0,0 +1,510 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+
+/**
+ * Unit test for {@link AbstractMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class AbstractMessageTest extends TestCase {
+ /**
+ * Extends AbstractMessage and wraps some other message object. The methods
+ * of the Message interface which aren't explicitly implemented by
+ * AbstractMessage are forwarded to the wrapped object. This allows us to
+ * test that AbstractMessage's implementations work even if the wrapped
+ * object does not use them.
+ */
+ private static class AbstractMessageWrapper extends AbstractMessage {
+ private final Message wrappedMessage;
+
+ public AbstractMessageWrapper(Message wrappedMessage) {
+ this.wrappedMessage = wrappedMessage;
+ }
+
+ public Descriptors.Descriptor getDescriptorForType() {
+ return wrappedMessage.getDescriptorForType();
+ }
+ public AbstractMessageWrapper getDefaultInstanceForType() {
+ return new AbstractMessageWrapper(
+ wrappedMessage.getDefaultInstanceForType());
+ }
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ return wrappedMessage.getAllFields();
+ }
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.hasField(field);
+ }
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.getField(field);
+ }
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.getRepeatedFieldCount(field);
+ }
+ public Object getRepeatedField(
+ Descriptors.FieldDescriptor field, int index) {
+ return wrappedMessage.getRepeatedField(field, index);
+ }
+ public UnknownFieldSet getUnknownFields() {
+ return wrappedMessage.getUnknownFields();
+ }
+ public Builder newBuilderForType() {
+ return new Builder(wrappedMessage.newBuilderForType());
+ }
+ public Builder toBuilder() {
+ return new Builder(wrappedMessage.toBuilder());
+ }
+
+ static class Builder extends AbstractMessage.Builder<Builder> {
+ private final Message.Builder wrappedBuilder;
+
+ public Builder(Message.Builder wrappedBuilder) {
+ this.wrappedBuilder = wrappedBuilder;
+ }
+
+ public AbstractMessageWrapper build() {
+ return new AbstractMessageWrapper(wrappedBuilder.build());
+ }
+ public AbstractMessageWrapper buildPartial() {
+ return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
+ }
+ public Builder clone() {
+ return new Builder(wrappedBuilder.clone());
+ }
+ public boolean isInitialized() {
+ return clone().buildPartial().isInitialized();
+ }
+ public Descriptors.Descriptor getDescriptorForType() {
+ return wrappedBuilder.getDescriptorForType();
+ }
+ public AbstractMessageWrapper getDefaultInstanceForType() {
+ return new AbstractMessageWrapper(
+ wrappedBuilder.getDefaultInstanceForType());
+ }
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ return wrappedBuilder.getAllFields();
+ }
+ public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
+ return new Builder(wrappedBuilder.newBuilderForField(field));
+ }
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.hasField(field);
+ }
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.getField(field);
+ }
+ public Builder setField(Descriptors.FieldDescriptor field, Object value) {
+ wrappedBuilder.setField(field, value);
+ return this;
+ }
+ public Builder clearField(Descriptors.FieldDescriptor field) {
+ wrappedBuilder.clearField(field);
+ return this;
+ }
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.getRepeatedFieldCount(field);
+ }
+ public Object getRepeatedField(
+ Descriptors.FieldDescriptor field, int index) {
+ return wrappedBuilder.getRepeatedField(field, index);
+ }
+ public Builder setRepeatedField(Descriptors.FieldDescriptor field,
+ int index, Object value) {
+ wrappedBuilder.setRepeatedField(field, index, value);
+ return this;
+ }
+ public Builder addRepeatedField(
+ Descriptors.FieldDescriptor field, Object value) {
+ wrappedBuilder.addRepeatedField(field, value);
+ return this;
+ }
+ public UnknownFieldSet getUnknownFields() {
+ return wrappedBuilder.getUnknownFields();
+ }
+ public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+ wrappedBuilder.setUnknownFields(unknownFields);
+ return this;
+ }
+ @Override
+ public Message.Builder getFieldBuilder(FieldDescriptor field) {
+ return wrappedBuilder.getFieldBuilder(field);
+ }
+ }
+ public Parser<? extends Message> getParserForType() {
+ return wrappedMessage.getParserForType();
+ }
+ }
+
+ // =================================================================
+
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+
+ public void testClear() throws Exception {
+ AbstractMessageWrapper message =
+ new AbstractMessageWrapper.Builder(
+ TestAllTypes.newBuilder(TestUtil.getAllSet()))
+ .clear().build();
+ TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testCopy() throws Exception {
+ AbstractMessageWrapper message =
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
+ .mergeFrom(TestUtil.getAllSet()).build();
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testSerializedSize() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+ assertEquals(message.getSerializedSize(),
+ abstractMessage.getSerializedSize());
+ }
+
+ public void testSerialization() throws Exception {
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+ TestUtil.assertAllFieldsSet(
+ TestAllTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getAllSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testParsingUninitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ builder.getOptionalMessageBuilder().setDummy2(10);
+ ByteString bytes = builder.buildPartial().toByteString();
+ Message.Builder abstractMessageBuilder =
+ new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+ // mergeFrom() should not throw initialization error.
+ abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ abstractMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+
+ // test DynamicMessage directly.
+ Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+ TestRequiredForeign.getDescriptor());
+ // mergeFrom() should not throw initialization error.
+ dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ dynamicMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+ }
+
+ public void testPackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getPackedSet());
+
+ TestUtil.assertPackedFieldsSet(
+ TestPackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getPackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testPackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getUnpackedSet());
+
+ TestUtil.assertUnpackedFieldsSet(
+ TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getUnpackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testOptimizedForSize() throws Exception {
+ // We're mostly only checking that this class was compiled successfully.
+ TestOptimizedForSize message =
+ TestOptimizedForSize.newBuilder().setI(1).build();
+ message = TestOptimizedForSize.parseFrom(message.toByteString());
+ assertEquals(2, message.getSerializedSize());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for isInitialized().
+
+ private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+ TestRequired.getDefaultInstance();
+ private static final TestRequired TEST_REQUIRED_INITIALIZED =
+ TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+ public void testIsInitialized() throws Exception {
+ TestRequired.Builder builder = TestRequired.newBuilder();
+ AbstractMessageWrapper.Builder abstractBuilder =
+ new AbstractMessageWrapper.Builder(builder);
+
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
+ builder.setA(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("b, c", abstractBuilder.getInitializationErrorString());
+ builder.setB(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("c", abstractBuilder.getInitializationErrorString());
+ builder.setC(1);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ public void testForeignIsInitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ AbstractMessageWrapper.Builder abstractBuilder =
+ new AbstractMessageWrapper.Builder(builder);
+
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "optional_message.a, optional_message.b, optional_message.c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for mergeFrom
+
+ static final TestAllTypes MERGE_SOURCE =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .build();
+
+ static final TestAllTypes MERGE_DEST =
+ TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+ .addRepeatedString("qux")
+ .build();
+
+ static final String MERGE_RESULT_TEXT =
+ "optional_int32: 1\n" +
+ "optional_int64: 2\n" +
+ "optional_string: \"foo\"\n" +
+ "optional_foreign_message {\n" +
+ " c: 3\n" +
+ "}\n" +
+ "repeated_string: \"qux\"\n" +
+ "repeated_string: \"bar\"\n";
+
+ public void testMergeFrom() throws Exception {
+ AbstractMessageWrapper result =
+ new AbstractMessageWrapper.Builder(
+ TestAllTypes.newBuilder(MERGE_DEST))
+ .mergeFrom(MERGE_SOURCE).build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for equals and hashCode
+
+ public void testEqualsAndHashCode() throws Exception {
+ TestAllTypes a = TestUtil.getAllSet();
+ TestAllTypes b = TestAllTypes.newBuilder().build();
+ TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
+ TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
+ TestAllExtensions e = TestUtil.getAllExtensionsSet();
+ TestAllExtensions f = TestAllExtensions.newBuilder(e)
+ .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+ checkEqualsIsConsistent(f);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(a, f);
+
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(b, f);
+
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(c, f);
+
+ checkNotEqual(d, e);
+ checkNotEqual(d, f);
+
+ checkNotEqual(e, f);
+
+ // Deserializing into the TestEmptyMessage such that every field
+ // is an {@link UnknownFieldSet.Field}.
+ UnittestProto.TestEmptyMessage eUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ UnittestProto.TestEmptyMessage fUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
+ checkNotEqual(eUnknownFields, fUnknownFields);
+ checkEqualsIsConsistent(eUnknownFields);
+ checkEqualsIsConsistent(fUnknownFields);
+
+ // Subsequent reconstitutions should be identical
+ UnittestProto.TestEmptyMessage eUnknownFields2 =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
+ }
+
+
+ /**
+ * Asserts that the given proto has symmetric equals and hashCode methods.
+ */
+ private void checkEqualsIsConsistent(Message message) {
+ // Object should be equal to itself.
+ assertEquals(message, message);
+
+ // Object should be equal to a dynamic copy of itself.
+ DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
+ checkEqualsIsConsistent(message, dynamic);
+ }
+
+ /**
+ * Asserts that the given protos are equal and have the same hash code.
+ */
+ private void checkEqualsIsConsistent(Message message1, Message message2) {
+ assertEquals(message1, message2);
+ assertEquals(message2, message1);
+ assertEquals(message2.hashCode(), message1.hashCode());
+ }
+
+ /**
+ * Asserts that the given protos are not equal and have different hash codes.
+ *
+ * @warning It's valid for non-equal objects to have the same hash code, so
+ * this test is stricter than it needs to be. However, this should happen
+ * relatively rarely.
+ */
+ private void checkNotEqual(Message m1, Message m2) {
+ String equalsError = String.format("%s should not be equal to %s", m1, m2);
+ assertFalse(equalsError, m1.equals(m2));
+ assertFalse(equalsError, m2.equals(m1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", m1, m2),
+ m1.hashCode() == m2.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java
new file mode 100644
index 0000000000..c838274369
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/BoundedByteStringTest.java
@@ -0,0 +1,56 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}. The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "BoundedByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+ int from = 100;
+ int to = sourceBytes.length - 100;
+ stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = 727575887;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java
new file mode 100644
index 0000000000..8bb9f731d2
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ByteStringTest.java
@@ -0,0 +1,590 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.ByteString.Output;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+ private static final String UTF_16 = "UTF-16";
+
+ static byte[] getTestBytes(int size, long seed) {
+ Random random = new Random(seed);
+ byte[] result = new byte[size];
+ random.nextBytes(result);
+ return result;
+ }
+
+ private byte[] getTestBytes(int size) {
+ return getTestBytes(size, 445566L);
+ }
+
+ private byte[] getTestBytes() {
+ return getTestBytes(1000);
+ }
+
+ // Compare the entire left array with a subset of the right array.
+ private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+ boolean stillEqual = (left.length == length);
+ for (int i = 0; (stillEqual && i < length); ++i) {
+ stillEqual = (left[i] == right[rightOffset + i]);
+ }
+ return stillEqual;
+ }
+
+ // Returns true only if the given two arrays have identical contents.
+ private boolean isArray(byte[] left, byte[] right) {
+ return left.length == right.length && isArrayRange(left, right, 0, left.length);
+ }
+
+ public void testSubstring_BeginIndex() {
+ byte[] bytes = getTestBytes();
+ ByteString substring = ByteString.copyFrom(bytes).substring(500);
+ assertTrue("substring must contain the tail of the string",
+ isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_BytesOffsetSize() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+ assertTrue("copyFrom sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_Bytes() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ assertTrue("copyFrom must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ public void testCopyFrom_ByteBufferSize() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_ByteBuffer() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_StringEncoding() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+ byte[] testBytes = testString.getBytes(UTF_16);
+ assertTrue("copyFrom string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Utf8() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFromUtf8(testString);
+ byte[] testBytes = testString.getBytes("UTF-8");
+ assertTrue("copyFromUtf8 string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Iterable() {
+ byte[] testBytes = getTestBytes(77777, 113344L);
+ final List<ByteString> pieces = makeConcretePieces(testBytes);
+ // Call copyFrom() on a Collection
+ ByteString byteString = ByteString.copyFrom(pieces);
+ assertTrue("copyFrom a List must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ // Call copyFrom on an iteration that's not a collection
+ ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+ public Iterator<ByteString> iterator() {
+ return pieces.iterator();
+ }
+ });
+ assertEquals("copyFrom from an Iteration must contain the expected bytes",
+ byteString, byteStringAlt);
+ }
+
+ public void testCopyTo_TargetOffset() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ byte[] target = new byte[bytes.length + 1000];
+ byteString.copyTo(target, 400);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(bytes, target, 400, bytes.length));
+ }
+
+ public void testReadFrom_emptyStream() throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+ assertSame("reading an empty stream must result in the EMPTY constant "
+ + "byte string", ByteString.EMPTY, byteString);
+ }
+
+ public void testReadFrom_smallStream() throws IOException {
+ assertReadFrom(getTestBytes(10));
+ }
+
+ public void testReadFrom_mutating() throws IOException {
+ byte[] capturedArray = null;
+ EvilInputStream eis = new EvilInputStream();
+ ByteString byteString = ByteString.readFrom(eis);
+
+ capturedArray = eis.capturedArray;
+ byte[] originalValue = byteString.toByteArray();
+ for (int x = 0; x < capturedArray.length; ++x) {
+ capturedArray[x] = (byte) 0;
+ }
+
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+ Arrays.equals(originalValue, newValue));
+ }
+
+ // Tests sizes that are over multi-segment rope threshold.
+ public void testReadFrom_largeStream() throws IOException {
+ assertReadFrom(getTestBytes(0x100));
+ assertReadFrom(getTestBytes(0x101));
+ assertReadFrom(getTestBytes(0x110));
+ assertReadFrom(getTestBytes(0x1000));
+ assertReadFrom(getTestBytes(0x1001));
+ assertReadFrom(getTestBytes(0x1010));
+ assertReadFrom(getTestBytes(0x10000));
+ assertReadFrom(getTestBytes(0x10001));
+ assertReadFrom(getTestBytes(0x10010));
+ }
+
+ // Tests that IOExceptions propagate through ByteString.readFrom().
+ public void testReadFrom_IOExceptions() {
+ try {
+ ByteString.readFrom(new FailStream());
+ fail("readFrom must throw the underlying IOException");
+
+ } catch (IOException e) {
+ assertEquals("readFrom must throw the expected exception",
+ "synthetic failure", e.getMessage());
+ }
+ }
+
+ // Tests that ByteString.readFrom works with streams that don't
+ // always fill their buffers.
+ public void testReadFrom_reluctantStream() throws IOException {
+ final byte[] data = getTestBytes(0x1000);
+
+ ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+
+ // Same test as above, but with some specific chunk sizes.
+ assertReadFromReluctantStream(data, 100);
+ assertReadFromReluctantStream(data, 248);
+ assertReadFromReluctantStream(data, 249);
+ assertReadFromReluctantStream(data, 250);
+ assertReadFromReluctantStream(data, 251);
+ assertReadFromReluctantStream(data, 0x1000);
+ assertReadFromReluctantStream(data, 0x1001);
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly from a
+ // reluctant stream with the given chunkSize parameter.
+ private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+ throws IOException {
+ ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(b.toByteArray(), bytes));
+ }
+
+ // Tests that ByteString.readFrom works with streams that implement
+ // available().
+ public void testReadFrom_available() throws IOException {
+ final byte[] data = getTestBytes(0x1001);
+
+ ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly.
+ private void assertReadFrom(byte[] bytes) throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(bytes));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ // A stream that fails when read.
+ private static final class FailStream extends InputStream {
+ @Override public int read() throws IOException {
+ throw new IOException("synthetic failure");
+ }
+ }
+
+ // A stream that simulates blocking by only producing 250 characters
+ // per call to read(byte[]).
+ private static class ReluctantStream extends InputStream {
+ protected final byte[] data;
+ protected int pos = 0;
+
+ public ReluctantStream(byte[] data) {
+ this.data = data;
+ }
+
+ @Override public int read() {
+ if (pos == data.length) {
+ return -1;
+ } else {
+ return data[pos++];
+ }
+ }
+
+ @Override public int read(byte[] buf) {
+ return read(buf, 0, buf.length);
+ }
+
+ @Override public int read(byte[] buf, int offset, int size) {
+ if (pos == data.length) {
+ return -1;
+ }
+ int count = Math.min(Math.min(size, data.length - pos), 250);
+ System.arraycopy(data, pos, buf, offset, count);
+ pos += count;
+ return count;
+ }
+ }
+
+ // Same as above, but also implements available().
+ private static final class AvailableStream extends ReluctantStream {
+ public AvailableStream(byte[] data) {
+ super(data);
+ }
+
+ @Override public int available() {
+ return Math.min(250, data.length - pos);
+ }
+ }
+
+ // A stream which exposes the byte array passed into read(byte[], int, int).
+ private static class EvilInputStream extends InputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public int read(byte[] buf, int off, int len) {
+ if (capturedArray != null) {
+ return -1;
+ } else {
+ capturedArray = buf;
+ for (int x = 0; x < len; ++x) {
+ buf[x] = (byte) x;
+ }
+ return len;
+ }
+ }
+
+ @Override
+ public int read() {
+ // Purposefully do nothing.
+ return -1;
+ }
+ }
+
+ // A stream which exposes the byte array passed into write(byte[], int, int).
+ private static class EvilOutputStream extends OutputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ if (capturedArray == null) {
+ capturedArray = buf;
+ }
+ }
+
+ @Override
+ public void write(int ignored) {
+ // Purposefully do nothing.
+ }
+ }
+
+ public void testToStringUtf8() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ byte[] testBytes = testString.getBytes("UTF-8");
+ ByteString byteString = ByteString.copyFrom(testBytes);
+ assertEquals("copyToStringUtf8 must respect the charset",
+ testString, byteString.toStringUtf8());
+ }
+
+ public void testNewOutput_InitialCapacity() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+ output.write(bytes);
+ ByteString byteString = output.toByteString();
+ assertTrue(
+ "String built from newOutput(int) must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+ // write sizes
+ public void testNewOutput_ArrayWrite() throws IOException {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+ for (int bufferSize : bufferSizes) {
+ for (int writeSize : writeSizes) {
+ // Test writing the entire output writeSize bytes at a time.
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (int i = 0; i < length; i += writeSize) {
+ output.write(bytes, i, Math.min(writeSize, length - i));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+ }
+
+ // Test newOutput() using a variety of buffer sizes, but writing all the
+ // characters using write(byte);
+ public void testNewOutput_WriteChar() throws IOException {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ for (int bufferSize : bufferSizes) {
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (byte byteValue : bytes) {
+ output.write(byteValue);
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ // Test newOutput() in which we write the bytes using a variety of methods
+ // and sizes, and in which we repeatedly call toByteString() in the middle.
+ public void testNewOutput_Mixed() throws IOException {
+ Random rng = new Random(1);
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+
+ for (int bufferSize : bufferSizes) {
+ // Test writing the entire output using a mixture of write sizes and
+ // methods;
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ int position = 0;
+ while (position < bytes.length) {
+ if (rng.nextBoolean()) {
+ int count = 1 + rng.nextInt(bytes.length - position);
+ output.write(bytes, position, count);
+ position += count;
+ } else {
+ output.write(bytes[position]);
+ position++;
+ }
+ assertEquals("size() returns the right value", position, output.size());
+ assertTrue("newOutput() substring must have correct bytes",
+ isArrayRange(output.toByteString().toByteArray(),
+ bytes, 0, position));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ public void testNewOutputEmpty() throws IOException {
+ // Make sure newOutput() correctly builds empty byte strings
+ ByteString byteString = ByteString.newOutput().toByteString();
+ assertEquals(ByteString.EMPTY, byteString);
+ }
+
+ public void testNewOutput_Mutating() throws IOException {
+ Output os = ByteString.newOutput(5);
+ os.write(new byte[] {1, 2, 3, 4, 5});
+ EvilOutputStream eos = new EvilOutputStream();
+ os.writeTo(eos);
+ byte[] capturedArray = eos.capturedArray;
+ ByteString byteString = os.toByteString();
+ byte[] oldValue = byteString.toByteArray();
+ Arrays.fill(capturedArray, (byte) 0);
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("Output must not provide access to the underlying byte array",
+ Arrays.equals(oldValue, newValue));
+ }
+
+ public void testSubstringParity() {
+ byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+ int start = 512 * 1024 - 3333;
+ int end = 512 * 1024 + 7777;
+ ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+ boolean ok = true;
+ for (int i = start; ok && i < end; ++i) {
+ ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+ }
+ assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+ ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+ assertTrue("Substring must be equal to literal string",
+ concreteSubstring.equals(literalString));
+ assertEquals("Substring must have same hashcode as literal string",
+ literalString.hashCode(), concreteSubstring.hashCode());
+ }
+
+ public void testCompositeSubstring() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ int from = 1000;
+ int to = 40000;
+ ByteString compositeSubstring = listString.substring(from, to);
+ byte[] substringBytes = compositeSubstring.toByteArray();
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == substringBytes[i];
+ }
+ assertTrue("Substring must return correct bytes", stillEqual);
+
+ stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+ }
+ assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+ ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+ assertTrue("Composite substring must equal a literal substring over the same bytes",
+ compositeSubstring.equals(literalSubstring));
+ assertTrue("Literal substring must equal a composite substring over the same bytes",
+ literalSubstring.equals(compositeSubstring));
+
+ assertEquals("We must get the same hashcodes for composite and literal substrings",
+ literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+ assertFalse("We can't be equal to a proper substring",
+ compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+ }
+
+ public void testCopyFromList() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ assertTrue("Composite string must be equal to literal string",
+ listString.equals(literalString));
+ assertEquals("Composite string must have same hashcode as literal string",
+ literalString.hashCode(), listString.hashCode());
+ }
+
+ public void testConcat() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+ Iterator<ByteString> iter = pieces.iterator();
+ ByteString concatenatedString = iter.next();
+ while (iter.hasNext()) {
+ concatenatedString = concatenatedString.concat(iter.next());
+ }
+
+ assertTrue("Concatenated string must be equal to literal string",
+ concatenatedString.equals(literalString));
+ assertEquals("Concatenated string must have same hashcode as literal string",
+ literalString.hashCode(), concatenatedString.hashCode());
+ }
+
+ public void testStartsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.startsWith(ByteString.EMPTY));
+ assertTrue(string.startsWith(string));
+ assertTrue(string.startsWith(prefix));
+ assertFalse(string.startsWith(suffix));
+ assertFalse(prefix.startsWith(suffix));
+ assertFalse(suffix.startsWith(prefix));
+ assertFalse(ByteString.EMPTY.startsWith(prefix));
+ assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+ }
+
+ static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+ List<ByteString> pieces = new ArrayList<ByteString>();
+ // Starting length should be small enough that we'll do some concatenating by
+ // copying if we just concatenate all these pieces together.
+ for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+ length = (length << 1) - 1;
+ if (start + length > referenceBytes.length) {
+ length = referenceBytes.length - start;
+ }
+ pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+ }
+ return pieces;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java
new file mode 100644
index 0000000000..7e67898ea4
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedInputStreamTest.java
@@ -0,0 +1,469 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRecursiveMessage;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * Unit test for {@link CodedInputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedInputStreamTest extends TestCase {
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /**
+ * An InputStream which limits the number of bytes it reads at a time.
+ * We use this to make sure that CodedInputStream doesn't screw up when
+ * reading in small blocks.
+ */
+ private static final class SmallBlockInputStream extends FilterInputStream {
+ private final int blockSize;
+
+ public SmallBlockInputStream(byte[] data, int blockSize) {
+ this(new ByteArrayInputStream(data), blockSize);
+ }
+
+ public SmallBlockInputStream(InputStream in, int blockSize) {
+ super(in);
+ this.blockSize = blockSize;
+ }
+
+ public int read(byte[] b) throws IOException {
+ return super.read(b, 0, Math.min(b.length, blockSize));
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ return super.read(b, off, Math.min(len, blockSize));
+ }
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+ * checks that the result matches the given value.
+ */
+ private void assertReadVarint(byte[] data, long value) throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals((int)value, input.readRawVarint32());
+
+ input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawVarint64());
+ assertTrue(input.isAtEnd());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals((int)value, input.readRawVarint32());
+
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawVarint64());
+ assertTrue(input.isAtEnd());
+ }
+
+ // Try reading direct from an InputStream. We want to verify that it
+ // doesn't read past the end of the input, so we copy to a new, bigger
+ // array first.
+ byte[] longerData = new byte[data.length + 1];
+ System.arraycopy(data, 0, longerData, 0, data.length);
+ InputStream rawInput = new ByteArrayInputStream(longerData);
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and
+ * expects them to fail with an InvalidProtocolBufferException whose
+ * description matches the given one.
+ */
+ private void assertReadVarintFailure(
+ InvalidProtocolBufferException expected, byte[] data)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ try {
+ input.readRawVarint32();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+
+ input = CodedInputStream.newInstance(data);
+ try {
+ input.readRawVarint64();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+ }
+
+ /** Tests readRawVarint32() and readRawVarint64(). */
+ public void testReadVarint() throws Exception {
+ assertReadVarint(bytes(0x00), 0);
+ assertReadVarint(bytes(0x01), 1);
+ assertReadVarint(bytes(0x7f), 127);
+ // 14882
+ assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertReadVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x1bL << 28));
+ // 41256202580718336
+ assertReadVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+ (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+ // 11964378330978735131
+ assertReadVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+ (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian32() and checks
+ * that the result matches the given value.
+ */
+ private void assertReadLittleEndian32(byte[] data, int value)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawLittleEndian32());
+ assertTrue(input.isAtEnd());
+ }
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian64() and checks
+ * that the result matches the given value.
+ */
+ private void assertReadLittleEndian64(byte[] data, long value)
+ throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(data, blockSize));
+ assertEquals(value, input.readRawLittleEndian64());
+ assertTrue(input.isAtEnd());
+ }
+ }
+
+ /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
+ public void testReadLittleEndian() throws Exception {
+ assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertReadLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+ 0x123456789abcdef0L);
+ assertReadLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
+ 0x9abcdef012345678L);
+ }
+
+ /** Test decodeZigZag32() and decodeZigZag64(). */
+ public void testDecodeZigZag() throws Exception {
+ assertEquals( 0, CodedInputStream.decodeZigZag32(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag32(1));
+ assertEquals( 1, CodedInputStream.decodeZigZag32(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag32(3));
+ assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
+ assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
+ assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
+
+ assertEquals( 0, CodedInputStream.decodeZigZag64(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag64(1));
+ assertEquals( 1, CodedInputStream.decodeZigZag64(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag64(3));
+ assertEquals(0x000000003FFFFFFFL,
+ CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
+ assertEquals(0xFFFFFFFFC0000000L,
+ CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL,
+ CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
+ assertEquals(0xFFFFFFFF80000000L,
+ CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
+ assertEquals(0x7FFFFFFFFFFFFFFFL,
+ CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+ assertEquals(0x8000000000000000L,
+ CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+ }
+
+ /** Tests reading and parsing a whole message with every field type. */
+ public void testReadWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEquals(rawBytes.length, message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+ TestUtil.assertAllFieldsSet(message2);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ message2 = TestAllTypes.parseFrom(
+ new SmallBlockInputStream(rawBytes, blockSize));
+ TestUtil.assertAllFieldsSet(message2);
+ }
+ }
+
+ /** Tests skipField(). */
+ public void testSkipWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+ byte[] rawBytes = message.toByteArray();
+
+ // Create two parallel inputs. Parse one as unknown fields while using
+ // skipField() to skip each field on the other. Expect the same tags.
+ CodedInputStream input1 = CodedInputStream.newInstance(rawBytes);
+ CodedInputStream input2 = CodedInputStream.newInstance(rawBytes);
+ UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
+
+ while (true) {
+ int tag = input1.readTag();
+ assertEquals(tag, input2.readTag());
+ if (tag == 0) {
+ break;
+ }
+ unknownFields.mergeFieldFrom(tag, input1);
+ input2.skipField(tag);
+ }
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * exactly up to a limit, this should not break things.
+ */
+ public void testSkipRawBytesBug() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2 };
+ CodedInputStream input = CodedInputStream.newInstance(rawBytes);
+
+ int limit = input.pushLimit(1);
+ input.skipRawBytes(1);
+ input.popLimit(limit);
+ assertEquals(2, input.readRawByte());
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips
+ * past the end of a buffer with a limit that has been set past the end of
+ * that buffer, this should not break things.
+ */
+ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+ byte[] rawBytes = new byte[] { 1, 2, 3, 4, 5 };
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(rawBytes, 3));
+
+ int limit = input.pushLimit(4);
+ // In order to expose the bug we need to read at least one byte to prime the
+ // buffer inside the CodedInputStream.
+ assertEquals(1, input.readRawByte());
+ // Skip to the end of the limit.
+ input.skipRawBytes(3);
+ assertTrue(input.isAtEnd());
+ input.popLimit(limit);
+ assertEquals(5, input.readRawByte());
+ }
+
+ public void testReadHugeBlob() throws Exception {
+ // Allocate and initialize a 1MB blob.
+ byte[] blob = new byte[1 << 20];
+ for (int i = 0; i < blob.length; i++) {
+ blob[i] = (byte)i;
+ }
+
+ // Make a message containing it.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ builder.setOptionalBytes(ByteString.copyFrom(blob));
+ TestAllTypes message = builder.build();
+
+ // Serialize and parse it. Make sure to parse from an InputStream, not
+ // directly from a ByteString, so that CodedInputStream uses buffered
+ // reading.
+ TestAllTypes message2 =
+ TestAllTypes.parseFrom(message.toByteString().newInput());
+
+ assertEquals(message.getOptionalBytes(), message2.getOptionalBytes());
+
+ // Make sure all the other fields were parsed correctly.
+ TestAllTypes message3 = TestAllTypes.newBuilder(message2)
+ .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
+ .build();
+ TestUtil.assertAllFieldsSet(message3);
+ }
+
+ public int makeTag(int number, int tag) {
+ return (number << 3) + tag;
+ }
+
+ public void testReadMaliciouslyLargeBlob() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(0x7FFFFFFF);
+ output.writeRawBytes(new byte[32]); // Pad with a few random bytes.
+ output.flush();
+
+ CodedInputStream input = rawOutput.toByteString().newCodedInput();
+ assertEquals(tag, input.readTag());
+
+ try {
+ input.readBytes();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+
+ private TestRecursiveMessage makeRecursiveMessage(int depth) {
+ if (depth == 0) {
+ return TestRecursiveMessage.newBuilder().setI(5).build();
+ } else {
+ return TestRecursiveMessage.newBuilder()
+ .setA(makeRecursiveMessage(depth - 1)).build();
+ }
+ }
+
+ private void assertMessageDepth(TestRecursiveMessage message, int depth) {
+ if (depth == 0) {
+ assertFalse(message.hasA());
+ assertEquals(5, message.getI());
+ } else {
+ assertTrue(message.hasA());
+ assertMessageDepth(message.getA(), depth - 1);
+ }
+ }
+
+ public void testResetSizeCounter() throws Exception {
+ CodedInputStream input = CodedInputStream.newInstance(
+ new SmallBlockInputStream(new byte[256], 8));
+ input.setSizeLimit(16);
+ input.readRawBytes(16);
+ assertEquals(16, input.getTotalBytesRead());
+
+ try {
+ input.readRawByte();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ input.readRawByte(); // No exception thrown.
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ }
+
+ /**
+ * Tests that if we read an string that contains invalid UTF-8, no exception
+ * is thrown. Instead, the invalid bytes are replaced with the Unicode
+ * "replacement character" U+FFFD.
+ */
+ public void testReadInvalidUtf8() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] { (byte)0x80 });
+ output.flush();
+
+ CodedInputStream input = rawOutput.toByteString().newCodedInput();
+ assertEquals(tag, input.readTag());
+ String text = input.readString();
+ assertEquals(0xfffd, text.charAt(0));
+ }
+
+ public void testReadFromSlice() throws Exception {
+ byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
+ assertEquals(0, in.getTotalBytesRead());
+ for (int i = 3; i < 8; i++) {
+ assertEquals(i, in.readRawByte());
+ assertEquals(i-2, in.getTotalBytesRead());
+ }
+ // eof
+ assertEquals(0, in.readTag());
+ assertEquals(5, in.getTotalBytesRead());
+ }
+
+ public void testInvalidTag() throws Exception {
+ // Any tag number which corresponds to field number zero is invalid and
+ // should throw InvalidProtocolBufferException.
+ for (int i = 0; i < 8; i++) {
+ try {
+ CodedInputStream.newInstance(bytes(i)).readTag();
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java
new file mode 100644
index 0000000000..354d89d664
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/CodedOutputStreamTest.java
@@ -0,0 +1,318 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto.SparseEnumMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit test for {@link CodedOutputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedOutputStreamTest extends TestCase {
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /** Arrays.asList() does not work with arrays of primitives. :( */
+ private List<Byte> toList(byte[] bytes) {
+ List<Byte> result = new ArrayList<Byte>();
+ for (byte b : bytes) {
+ result.add(b);
+ }
+ return result;
+ }
+
+ private void assertEqualBytes(byte[] a, byte[] b) {
+ assertEquals(toList(a), toList(b));
+ }
+
+ /**
+ * Writes the given value using writeRawVarint32() and writeRawVarint64() and
+ * checks that the result matches the given bytes.
+ */
+ private void assertWriteVarint(byte[] data, long value) throws Exception {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if ((value >>> 32) == 0) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint32((int) value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length,
+ CodedOutputStream.computeRawVarint32Size((int) value));
+ }
+
+ {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawVarint64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length,
+ CodedOutputStream.computeRawVarint64Size(value));
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if ((value >>> 32) == 0) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawVarint32((int) value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+
+ {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawVarint64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+ }
+
+ /** Tests writeRawVarint32() and writeRawVarint64(). */
+ public void testWriteVarint() throws Exception {
+ assertWriteVarint(bytes(0x00), 0);
+ assertWriteVarint(bytes(0x01), 1);
+ assertWriteVarint(bytes(0x7f), 127);
+ // 14882
+ assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertWriteVarint(bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
+ (0x1bL << 28));
+ // 41256202580718336
+ assertWriteVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
+ (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
+ // 11964378330978735131
+ assertWriteVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bL << 28) | (0x56L << 35) | (0x00L << 42) |
+ (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian32() and checks
+ * that the result matches the given value.
+ */
+ private void assertWriteLittleEndian32(byte[] data, int value)
+ throws Exception {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawLittleEndian32(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = new ByteArrayOutputStream();
+ output = CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawLittleEndian32(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian64() and checks
+ * that the result matches the given value.
+ */
+ private void assertWriteLittleEndian64(byte[] data, long value)
+ throws Exception {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ output.writeRawLittleEndian64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = new ByteArrayOutputStream();
+ output = CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeRawLittleEndian64(value);
+ output.flush();
+ assertEqualBytes(data, rawOutput.toByteArray());
+ }
+ }
+
+ /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
+ public void testWriteLittleEndian() throws Exception {
+ assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertWriteLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12),
+ 0x123456789abcdef0L);
+ assertWriteLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a),
+ 0x9abcdef012345678L);
+ }
+
+ /** Test encodeZigZag32() and encodeZigZag64(). */
+ public void testEncodeZigZag() throws Exception {
+ assertEquals(0, CodedOutputStream.encodeZigZag32( 0));
+ assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag32( 1));
+ assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
+ assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
+ assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
+ assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
+
+ assertEquals(0, CodedOutputStream.encodeZigZag64( 0));
+ assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag64( 1));
+ assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
+ assertEquals(0x000000007FFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
+ assertEquals(0x00000000FFFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x00000000FFFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
+ assertEquals(0xFFFFFFFFFFFFFFFEL,
+ CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
+ assertEquals(0xFFFFFFFFFFFFFFFFL,
+ CodedOutputStream.encodeZigZag64(0x8000000000000000L));
+
+ // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
+ // were chosen semi-randomly via keyboard bashing.
+ assertEquals(0,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
+ assertEquals(1,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
+ assertEquals(-1,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
+ assertEquals(14927,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
+ assertEquals(-3612,
+ CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
+
+ assertEquals(0,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
+ assertEquals(1,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
+ assertEquals(-1,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
+ assertEquals(14927,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
+ assertEquals(-3612,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
+
+ assertEquals(856912304801416L,
+ CodedOutputStream.encodeZigZag64(
+ CodedInputStream.decodeZigZag64(
+ 856912304801416L)));
+ assertEquals(-75123905439571256L,
+ CodedOutputStream.encodeZigZag64(
+ CodedInputStream.decodeZigZag64(
+ -75123905439571256L)));
+ }
+
+ /** Tests writing a whole message with every field type. */
+ public void testWriteWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEqualBytes(TestUtil.getGoldenMessage().toByteArray(), rawBytes);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output =
+ CodedOutputStream.newInstance(rawOutput, blockSize);
+ message.writeTo(output);
+ output.flush();
+ assertEqualBytes(rawBytes, rawOutput.toByteArray());
+ }
+ }
+
+ /** Tests writing a whole message with every packed field type. Ensures the
+ * wire format of packed fields is compatible with C++. */
+ public void testWriteWholePackedFieldsMessage() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEqualBytes(TestUtil.getGoldenPackedFieldsMessage().toByteArray(),
+ rawBytes);
+ }
+
+ /** Test writing a message containing a negative enum value. This used to
+ * fail because the size was not properly computed as a sign-extended varint.
+ */
+ public void testWriteMessageWithNegativeEnumValue() throws Exception {
+ SparseEnumMessage message = SparseEnumMessage.newBuilder()
+ .setSparseEnum(TestSparseEnum.SPARSE_E) .build();
+ assertTrue(message.getSparseEnum().getNumber() < 0);
+ byte[] rawBytes = message.toByteArray();
+ SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+ assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java
new file mode 100644
index 0000000000..ee4e767520
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DeprecatedFieldTest.java
@@ -0,0 +1,81 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto.TestDeprecatedFields;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+/**
+ * Test field deprecation
+ *
+ * @author birdo@google.com (Roberto Scaramuzzi)
+ */
+public class DeprecatedFieldTest extends TestCase {
+ private String[] deprecatedGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32"};
+
+ private String[] deprecatedBuilderGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32",
+ "clearDeprecatedInt32"};
+
+ private String[] deprecatedBuilderSetterNames = {
+ "setDeprecatedInt32"};
+
+ public void testDeprecatedField() throws Exception {
+ Class<?> deprecatedFields = TestDeprecatedFields.class;
+ Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
+ for (String name : deprecatedGetterNames) {
+ Method method = deprecatedFields.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderGetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderSetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ }
+
+ private boolean isDeprecated(AnnotatedElement annotated) {
+ return annotated.isAnnotationPresent(Deprecated.class);
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java
new file mode 100644
index 0000000000..aabd7b4d73
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DescriptorsTest.java
@@ -0,0 +1,649 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.ServiceDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+
+import com.google.protobuf.test.UnittestImport;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestService;
+import protobuf_unittest.UnittestCustomOptions;
+
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit test for {@link Descriptors}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DescriptorsTest extends TestCase {
+
+ // Regression test for bug where referencing a FieldDescriptor.Type value
+ // before a FieldDescriptorProto.Type value would yield a
+ // ExceptionInInitializerError.
+ @SuppressWarnings("unused")
+ private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+ public void testFieldTypeEnumMapping() throws Exception {
+ assertEquals(FieldDescriptor.Type.values().length,
+ FieldDescriptorProto.Type.values().length);
+ for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+ FieldDescriptorProto.Type protoType = type.toProto();
+ assertEquals("TYPE_" + type.name(), protoType.name());
+ assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+ }
+ }
+
+ public void testFileDescriptor() throws Exception {
+ FileDescriptor file = UnittestProto.getDescriptor();
+
+ assertEquals("google/protobuf/unittest.proto", file.getName());
+ assertEquals("protobuf_unittest", file.getPackage());
+
+ assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
+ assertEquals("google/protobuf/unittest.proto",
+ file.toProto().getName());
+
+ assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
+ file.getDependencies());
+
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ assertEquals(messageType, file.getMessageTypes().get(0));
+ assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
+ assertNull(file.findMessageTypeByName("NoSuchType"));
+ assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
+ for (int i = 0; i < file.getMessageTypes().size(); i++) {
+ assertEquals(i, file.getMessageTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ assertEquals(enumType, file.getEnumTypes().get(0));
+ assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
+ assertNull(file.findEnumTypeByName("NoSuchType"));
+ assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
+ assertEquals(Arrays.asList(ImportEnum.getDescriptor()),
+ UnittestImport.getDescriptor().getEnumTypes());
+ for (int i = 0; i < file.getEnumTypes().size(); i++) {
+ assertEquals(i, file.getEnumTypes().get(i).getIndex());
+ }
+
+ ServiceDescriptor service = TestService.getDescriptor();
+ assertEquals(service, file.getServices().get(0));
+ assertEquals(service, file.findServiceByName("TestService"));
+ assertNull(file.findServiceByName("NoSuchType"));
+ assertNull(file.findServiceByName("protobuf_unittest.TestService"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getServices());
+ for (int i = 0; i < file.getServices().size(); i++) {
+ assertEquals(i, file.getServices().get(i).getIndex());
+ }
+
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ assertEquals(extension, file.getExtensions().get(0));
+ assertEquals(extension,
+ file.findExtensionByName("optional_int32_extension"));
+ assertNull(file.findExtensionByName("no_such_ext"));
+ assertNull(file.findExtensionByName(
+ "protobuf_unittest.optional_int32_extension"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getExtensions());
+ for (int i = 0; i < file.getExtensions().size(); i++) {
+ assertEquals(i, file.getExtensions().get(i).getIndex());
+ }
+ }
+
+ public void testDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
+
+ assertEquals("TestAllTypes", messageType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
+ assertNull(messageType.getContainingType());
+ assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
+ messageType.getOptions());
+ assertEquals("TestAllTypes", messageType.toProto().getName());
+
+ assertEquals("NestedMessage", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(messageType, nestedType.getContainingType());
+
+ FieldDescriptor field = messageType.getFields().get(0);
+ assertEquals("optional_int32", field.getName());
+ assertEquals(field, messageType.findFieldByName("optional_int32"));
+ assertNull(messageType.findFieldByName("no_such_field"));
+ assertEquals(field, messageType.findFieldByNumber(1));
+ assertNull(messageType.findFieldByNumber(571283));
+ for (int i = 0; i < messageType.getFields().size(); i++) {
+ assertEquals(i, messageType.getFields().get(i).getIndex());
+ }
+
+ assertEquals(nestedType, messageType.getNestedTypes().get(0));
+ assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
+ assertNull(messageType.findNestedTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
+ assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+ assertEquals(enumType, messageType.getEnumTypes().get(0));
+ assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
+ assertNull(messageType.findEnumTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
+ assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
+ }
+ }
+
+ public void testFieldDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ FieldDescriptor primitiveField =
+ messageType.findFieldByName("optional_int32");
+ FieldDescriptor enumField =
+ messageType.findFieldByName("optional_nested_enum");
+ FieldDescriptor messageField =
+ messageType.findFieldByName("optional_foreign_message");
+ FieldDescriptor cordField =
+ messageType.findFieldByName("optional_cord");
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
+
+ assertEquals("optional_int32", primitiveField.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
+ primitiveField.getFullName());
+ assertEquals(1, primitiveField.getNumber());
+ assertEquals(messageType, primitiveField.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ primitiveField.getOptions());
+ assertFalse(primitiveField.isExtension());
+ assertEquals("optional_int32", primitiveField.toProto().getName());
+
+ assertEquals("optional_nested_enum", enumField.getName());
+ assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
+ assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
+ assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
+ enumField.getEnumType());
+
+ assertEquals("optional_foreign_message", messageField.getName());
+ assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
+ assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
+ assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
+
+ assertEquals("optional_cord", cordField.getName());
+ assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
+ assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
+ cordField.getOptions().getCtype());
+
+ assertEquals("optional_int32_extension", extension.getName());
+ assertEquals("protobuf_unittest.optional_int32_extension",
+ extension.getFullName());
+ assertEquals(1, extension.getNumber());
+ assertEquals(TestAllExtensions.getDescriptor(),
+ extension.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), extension.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, extension.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ extension.getOptions());
+ assertTrue(extension.isExtension());
+ assertEquals(null, extension.getExtensionScope());
+ assertEquals("optional_int32_extension", extension.toProto().getName());
+
+ assertEquals("single", nestedExtension.getName());
+ assertEquals("protobuf_unittest.TestRequired.single",
+ nestedExtension.getFullName());
+ assertEquals(TestRequired.getDescriptor(),
+ nestedExtension.getExtensionScope());
+ }
+
+ public void testFieldDescriptorLabel() throws Exception {
+ FieldDescriptor requiredField =
+ TestRequired.getDescriptor().findFieldByName("a");
+ FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+ FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+
+ assertTrue(requiredField.isRequired());
+ assertFalse(requiredField.isRepeated());
+ assertFalse(optionalField.isRequired());
+ assertFalse(optionalField.isRepeated());
+ assertFalse(repeatedField.isRequired());
+ assertTrue(repeatedField.isRepeated());
+ }
+
+ public void testFieldDescriptorDefault() throws Exception {
+ Descriptor d = TestAllTypes.getDescriptor();
+ assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
+ assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
+ assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
+ assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
+
+ d = TestExtremeDefaultValues.getDescriptor();
+ assertEquals(
+ ByteString.copyFrom(
+ "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes("ISO-8859-1")),
+ d.findFieldByName("escaped_bytes").getDefaultValue());
+ assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
+ assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
+ }
+
+ public void testEnumDescriptor() throws Exception {
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
+
+ assertEquals("ForeignEnum", enumType.getName());
+ assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
+ assertNull(enumType.getContainingType());
+ assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
+ enumType.getOptions());
+
+ assertEquals("NestedEnum", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
+
+ EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
+ assertEquals(value, enumType.getValues().get(0));
+ assertEquals("FOREIGN_FOO", value.getName());
+ assertEquals(4, value.getNumber());
+ assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
+ assertEquals(value, enumType.findValueByNumber(4));
+ assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
+ for (int i = 0; i < enumType.getValues().size(); i++) {
+ assertEquals(i, enumType.getValues().get(i).getIndex());
+ }
+ }
+
+ public void testServiceDescriptor() throws Exception {
+ ServiceDescriptor service = TestService.getDescriptor();
+
+ assertEquals("TestService", service.getName());
+ assertEquals("protobuf_unittest.TestService", service.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), service.getFile());
+
+ assertEquals(2, service.getMethods().size());
+
+ MethodDescriptor fooMethod = service.getMethods().get(0);
+ assertEquals("Foo", fooMethod.getName());
+ assertEquals(UnittestProto.FooRequest.getDescriptor(),
+ fooMethod.getInputType());
+ assertEquals(UnittestProto.FooResponse.getDescriptor(),
+ fooMethod.getOutputType());
+ assertEquals(fooMethod, service.findMethodByName("Foo"));
+
+ MethodDescriptor barMethod = service.getMethods().get(1);
+ assertEquals("Bar", barMethod.getName());
+ assertEquals(UnittestProto.BarRequest.getDescriptor(),
+ barMethod.getInputType());
+ assertEquals(UnittestProto.BarResponse.getDescriptor(),
+ barMethod.getOutputType());
+ assertEquals(barMethod, service.findMethodByName("Bar"));
+
+ assertNull(service.findMethodByName("NoSuchMethod"));
+
+ for (int i = 0; i < service.getMethods().size(); i++) {
+ assertEquals(i, service.getMethods().get(i).getIndex());
+ }
+ }
+
+
+ public void testCustomOptions() throws Exception {
+ Descriptor descriptor =
+ UnittestCustomOptions.TestMessageWithCustomOptions.getDescriptor();
+
+ assertTrue(
+ descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
+ assertEquals(Integer.valueOf(-56),
+ descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
+
+ FieldDescriptor field = descriptor.findFieldByName("field1");
+ assertNotNull(field);
+
+ assertTrue(
+ field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
+ assertEquals(Long.valueOf(8765432109L),
+ field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
+
+ EnumDescriptor enumType =
+ UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
+
+ assertTrue(
+ enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
+ assertEquals(Integer.valueOf(-789),
+ enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
+
+ ServiceDescriptor service =
+ UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
+
+ assertTrue(
+ service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
+ assertEquals(Long.valueOf(-9876543210L),
+ service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
+
+ MethodDescriptor method = service.findMethodByName("Foo");
+ assertNotNull(method);
+
+ assertTrue(
+ method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
+ assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
+ method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
+ }
+
+ /**
+ * Test that the FieldDescriptor.Type enum is the same as the
+ * WireFormat.FieldType enum.
+ */
+ public void testFieldTypeTablesMatch() throws Exception {
+ FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+ WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ /**
+ * Test that the FieldDescriptor.JavaType enum is the same as the
+ * WireFormat.JavaType enum.
+ */
+ public void testJavaTypeTablesMatch() throws Exception {
+ FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+ WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ public void testEnormousDescriptor() throws Exception {
+ // The descriptor for this file is larger than 64k, yet it did not cause
+ // a compiler error due to an over-long string literal.
+ assertTrue(
+ UnittestEnormousDescriptor.getDescriptor()
+ .toProto().getSerializedSize() > 65536);
+ }
+
+ /**
+ * Tests that the DescriptorValidationException works as intended.
+ */
+ public void testDescriptorValidatorException() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .setDefaultValue("invalid")
+ .build())
+ .build())
+ .build();
+ try {
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ // Expected; check that the error message contains some useful hints
+ assertTrue(e.getMessage().indexOf("foo") != -1);
+ assertTrue(e.getMessage().indexOf("Foo") != -1);
+ assertTrue(e.getMessage().indexOf("invalid") != -1);
+ assertTrue(e.getCause() instanceof NumberFormatException);
+ assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+ }
+ }
+
+ /**
+ * Tests the translate/crosslink for an example where a message field's name
+ * and type name are the same.
+ */
+ public void testDescriptorComplexCrosslink() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Bar")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Foo")
+ .setName("Foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .build();
+ // translate and crosslink
+ FileDescriptor file =
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ // verify resulting descriptors
+ assertNotNull(file);
+ List<Descriptor> msglist = file.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 2);
+ boolean barFound = false;
+ for (Descriptor desc : msglist) {
+ if (desc.getName().equals("Bar")) {
+ barFound = true;
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+ assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+ }
+ }
+ assertTrue(barFound);
+ }
+
+ public void testInvalidPublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto") .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("boo.proto")
+ .addDependency("foo.proto")
+ .addPublicDependency(1) // Error, should be 0.
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ try {
+ Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(
+ e.getMessage().indexOf("Invalid public dependency index.") != -1);
+ }
+ }
+
+ public void testHiddenDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[] {barFile});
+
+ try {
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(e.getMessage().indexOf("Bar") != -1);
+ assertTrue(e.getMessage().indexOf("is not defined") != -1);
+ }
+ }
+
+ public void testPublicDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[]{barFile});
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ }
+
+ /**
+ * Tests the translate/crosslink for an example with a more complex namespace
+ * referencing.
+ */
+ public void testComplexNamespacePublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .setPackage("a.b.c.d.bar.shared")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("MyEnum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("BLAH")
+ .setNumber(1)))
+ .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("bar.proto")
+ .setPackage("a.b.c.d.foo.shared")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("MyMessage")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setTypeName("bar.shared.MyEnum")
+ .setName("MyField")
+ .setNumber(1)))
+ .build();
+ // translate and crosslink
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[]{fooFile});
+ // verify resulting descriptors
+ assertNotNull(barFile);
+ List<Descriptor> msglist = barFile.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 1);
+ Descriptor desc = msglist.get(0);
+ if (desc.getName().equals("MyMessage")) {
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ FieldDescriptor field = fieldlist.get(0);
+ assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+ assertTrue(field.getEnumType().getName().equals("MyEnum"));
+ assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+ assertTrue(field.getEnumType().getFile().getPackage().equals(
+ "a.b.c.d.bar.shared"));
+ }
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java
new file mode 100644
index 0000000000..00230678fb
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/DynamicMessageTest.java
@@ -0,0 +1,265 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+
+import junit.framework.TestCase;
+import java.util.Arrays;
+
+/**
+ * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which
+ * tests some {@link DynamicMessage} functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DynamicMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+ TestUtil.ReflectionTester packedReflectionTester =
+ new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
+
+ public void testDynamicMessageAccessors() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testSettersAfterBuild() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ Message firstMessage = builder.build();
+ // double build()
+ builder.build();
+ // clear() after build()
+ builder.clear();
+ // setters after build()
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ // repeated setters after build()
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ // firstMessage shouldn't have been modified.
+ reflectionTester.assertClearViaReflection(firstMessage);
+ }
+
+ public void testUnknownFields() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+ .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+ .build());
+ Message message = builder.build();
+ assertEquals(2, message.getUnknownFields().asMap().size());
+ // clone() with unknown fields
+ Message.Builder newBuilder = builder.clone();
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ // clear() with unknown fields
+ newBuilder.clear();
+ assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+ // serialize/parse with unknown fields
+ newBuilder.mergeFrom(message.toByteString());
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ }
+
+ public void testDynamicMessageSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageExtensionAccessors() throws Exception {
+ // We don't need to extensively test DynamicMessage's handling of
+ // extensions because, frankly, it doesn't do anything special with them.
+ // It treats them just like any other fields.
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageRepeatedSetters() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ }
+
+ public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
+ }
+
+ public void testDynamicMessageSerializedSize() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ Message.Builder dynamicBuilder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
+ Message dynamicMessage = dynamicBuilder.build();
+
+ assertEquals(message.getSerializedSize(),
+ dynamicMessage.getSerializedSize());
+ }
+
+ public void testDynamicMessageSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getAllSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessageParsing() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageExtensionParsing() throws Exception {
+ ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+ Message message = DynamicMessage.parseFrom(
+ TestAllExtensions.getDescriptor(), rawBytes,
+ TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+ // Test Parser interface.
+ Message message2 = message.getParserForType().parseFrom(
+ rawBytes, TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
+ }
+
+ public void testDynamicMessagePackedSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
+ packedReflectionTester.setPackedFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessagePackedParsing() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestUtil.setPackedFields(builder);
+ TestPackedTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageCopy() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ DynamicMessage copy = DynamicMessage.newBuilder(message).build();
+ reflectionTester.assertAllFieldsSetViaReflection(copy);
+ }
+
+ public void testToBuilder() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ int unknownFieldNum = 9;
+ long unknownFieldVal = 90;
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(unknownFieldNum,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(unknownFieldVal).build())
+ .build());
+ DynamicMessage message = builder.build();
+
+ DynamicMessage derived = message.toBuilder().build();
+ reflectionTester.assertAllFieldsSetViaReflection(derived);
+ assertEquals(Arrays.asList(unknownFieldVal),
+ derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java
new file mode 100644
index 0000000000..6a39500ead
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ForceFieldBuildersPreRun.java
@@ -0,0 +1,49 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+/**
+ * A prerun for a test suite that allows running the full protocol buffer
+ * tests in a mode that disables the optimization for not using
+ * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
+ * requested. This allows us to run all the tests through both code paths
+ * and ensures that both code paths produce identical results.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class ForceFieldBuildersPreRun implements Runnable {
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public void run() {
+ // GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java
new file mode 100644
index 0000000000..49f114643c
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/GeneratedMessageTest.java
@@ -0,0 +1,961 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.test.UnittestImport;
+import protobuf_unittest.EnumWithNoOuter;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.MultipleFilesTestProto;
+import protobuf_unittest.NestedExtension.MyNestedExtension;
+import protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
+import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Unit test for generated messages and generated code. See also
+ * {@link MessageTest}, which tests some generated message functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class GeneratedMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ public void testDefaultInstance() throws Exception {
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.getDefaultInstance().getDefaultInstanceForType());
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.newBuilder().getDefaultInstanceForType());
+ }
+
+ public void testMessageOrBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testUsingBuilderMultipleTimes() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // primitive field scalar and repeated
+ builder.setOptionalSfixed64(100);
+ builder.addRepeatedInt32(100);
+ // enum field scalar and repeated
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ // proto field scalar and repeated
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
+ builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
+
+ TestAllTypes value1 = builder.build();
+
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure that builder didn't update previously created values
+ builder.setOptionalSfixed64(200);
+ builder.setRepeatedInt32(0, 200);
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
+ builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
+
+ TestAllTypes value2 = builder.build();
+
+ // Make sure value1 didn't change.
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure value2 is correct
+ assertEquals(200, value2.getOptionalSfixed64());
+ assertEquals(200, value2.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getRepeatedImportEnum(0));
+ assertEquals(2, value2.getOptionalForeignMessage().getC());
+ assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testRepeatedArraysAreImmutable() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedInt32(100);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+ assertIsUnmodifiable(builder.getRepeatedInt32List());
+ assertIsUnmodifiable(builder.getRepeatedImportEnumList());
+ assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(builder.getRepeatedFloatList());
+
+
+ TestAllTypes value = builder.build();
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ }
+
+ public void testParsedMessagesAreImmutable() throws Exception {
+ TestAllTypes value = TestAllTypes.PARSER.parseFrom(
+ TestUtil.getAllSet().toByteString());
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedInt64List());
+ assertIsUnmodifiable(value.getRepeatedUint32List());
+ assertIsUnmodifiable(value.getRepeatedUint64List());
+ assertIsUnmodifiable(value.getRepeatedSint32List());
+ assertIsUnmodifiable(value.getRepeatedSint64List());
+ assertIsUnmodifiable(value.getRepeatedFixed32List());
+ assertIsUnmodifiable(value.getRepeatedFixed64List());
+ assertIsUnmodifiable(value.getRepeatedSfixed32List());
+ assertIsUnmodifiable(value.getRepeatedSfixed64List());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ assertIsUnmodifiable(value.getRepeatedDoubleList());
+ assertIsUnmodifiable(value.getRepeatedBoolList());
+ assertIsUnmodifiable(value.getRepeatedStringList());
+ assertIsUnmodifiable(value.getRepeatedBytesList());
+ assertIsUnmodifiable(value.getRepeatedGroupList());
+ assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedImportMessageList());
+ assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ }
+
+ private void assertIsUnmodifiable(List<?> list) {
+ if (list == Collections.emptyList()) {
+ // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+ } else {
+ try {
+ list.clear();
+ fail("List wasn't immutable");
+ } catch (UnsupportedOperationException e) {
+ // good
+ }
+ }
+ }
+
+ public void testSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.setOptionalString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestUtil.modifyRepeatedFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addRepeatedString("one");
+ builder.addRepeatedString("two");
+ try {
+ builder.setRepeatedString(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedBytes(TestUtil.toBytes("one"));
+ builder.addRepeatedBytes(TestUtil.toBytes("two"));
+ try {
+ builder.setRepeatedBytes(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
+ try {
+ builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setRepeatedNestedMessage(
+ 1, (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ try {
+ builder.setRepeatedNestedEnum(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedAppend() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
+ builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
+
+ TestAllTypes message = builder.build();
+ assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
+ assertEquals(message.getRepeatedForeignEnumList(),
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+ assertEquals(1, message.getRepeatedForeignMessageCount());
+ assertEquals(12, message.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testRepeatedAppendRejectsNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ try {
+ builder.addAllRepeatedForeignMessage(
+ Arrays.asList(foreignMessage, (ForeignMessage) null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedForeignEnum(
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedString(Arrays.asList("one", null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testSettingForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(123).build())
+ .build();
+ // TODO(ngd): Upgrade to using real #equals method once implemented
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(456).build())
+ .build();
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testDefaults() throws Exception {
+ TestUtil.assertClear(TestAllTypes.getDefaultInstance());
+ TestUtil.assertClear(TestAllTypes.newBuilder().build());
+
+ TestExtremeDefaultValues message =
+ TestExtremeDefaultValues.getDefaultInstance();
+ assertEquals("\u1234", message.getUtf8String());
+ assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+ assertTrue(Double.isNaN(message.getNanDouble()));
+ assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+ assertTrue(Float.isNaN(message.getNanFloat()));
+ assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
+ }
+
+ public void testClear() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.assertClear(builder);
+ TestUtil.setAllFields(builder);
+ builder.clear();
+ TestUtil.assertClear(builder);
+ }
+
+ public void testReflectionGetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ reflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllTypes message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testReflectionSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllFieldsSet(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testReflectionSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testReflectionRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedFieldsModified(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testReflectionRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testReflectionDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.getDefaultInstance());
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.newBuilder().build());
+ }
+
+ public void testEnumInterface() throws Exception {
+ assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
+ instanceof ProtocolMessageEnum);
+ }
+
+ public void testEnumMap() throws Exception {
+ Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+ for (ForeignEnum value : ForeignEnum.values()) {
+ assertEquals(value, map.findValueByNumber(value.getNumber()));
+ }
+
+ assertTrue(map.findValueByNumber(12345) == null);
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ TestUnpackedTypes message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(message);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestPackedTypes message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet(message);
+ }
+
+ // =================================================================
+ // Extensions.
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+
+ public void testExtensionMessageOrBuilder() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.modifyRepeatedExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensions.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensions.newBuilder().build());
+ }
+
+ public void testExtensionReflectionGetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllExtensions message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testExtensionReflectionSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllExtensionsSet(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionReflectionSettersRejectNull() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testExtensionReflectionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedExtensionsModified(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionReflectionRepeatedSettersRejectNull()
+ throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
+ builder);
+ }
+
+ public void testExtensionReflectionDefaults() throws Exception {
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.getDefaultInstance());
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.newBuilder().build());
+ }
+
+ public void testClearExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1)
+ .clearExtension(UnittestProto.optionalInt32Extension)
+ .hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(0,
+ TestAllExtensions.newBuilder()
+ .addExtension(UnittestProto.repeatedInt32Extension, 1)
+ .clearExtension(UnittestProto.repeatedInt32Extension)
+ .getExtensionCount(UnittestProto.repeatedInt32Extension));
+ }
+
+ public void testExtensionCopy() throws Exception {
+ TestAllExtensions original = TestUtil.getAllExtensionsSet();
+ TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testExtensionMergeFrom() throws Exception {
+ TestAllExtensions original =
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1).build();
+ TestAllExtensions merged =
+ TestAllExtensions.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
+ }
+
+ // =================================================================
+ // multiple_files_test
+
+ public void testMultipleFilesOption() throws Exception {
+ // We mostly just want to check that things compile.
+ MessageWithNoOuter message =
+ MessageWithNoOuter.newBuilder()
+ .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1))
+ .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1))
+ .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
+ .setForeignEnum(EnumWithNoOuter.BAR)
+ .build();
+ assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString()));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ MessageWithNoOuter.getDescriptor().getFile());
+
+ Descriptors.FieldDescriptor field =
+ MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum");
+ assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(),
+ message.getField(field));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ ServiceWithNoOuter.getDescriptor().getFile());
+
+ assertFalse(
+ TestAllExtensions.getDefaultInstance().hasExtension(
+ MultipleFilesTestProto.extensionWithOuter));
+ }
+
+ public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize()
+ throws Exception {
+ TestOptionalOptimizedForSize message =
+ TestOptionalOptimizedForSize.getDefaultInstance();
+ assertTrue(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().buildPartial()
+ ).buildPartial();
+ assertFalse(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()
+ ).buildPartial();
+ assertTrue(message.isInitialized());
+ }
+
+ public void testUninitializedExtensionInOptimizedForSize()
+ throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().buildPartial());
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial());
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+ public void testToBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ TestUtil.assertAllFieldsSet(message.toBuilder().build());
+ }
+
+ public void testFieldConstantValues() throws Exception {
+ assertEquals(TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21);
+ assertEquals(TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31);
+ assertEquals(TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46);
+ assertEquals(TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48);
+ assertEquals(TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51);
+ }
+
+ public void testExtensionConstantValues() throws Exception {
+ assertEquals(UnittestProto.TestRequired.SINGLE_FIELD_NUMBER, 1000);
+ assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001);
+ assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1);
+ assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16);
+ assertEquals(
+ UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18);
+ assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21);
+ assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31);
+ assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46);
+ assertEquals(
+ UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
+ assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
+ }
+
+ public void testRecursiveMessageDefaultInstance() throws Exception {
+ UnittestProto.TestRecursiveMessage message =
+ UnittestProto.TestRecursiveMessage.getDefaultInstance();
+ assertTrue(message != null);
+ assertTrue(message.getA() != null);
+ assertTrue(message.getA() == message);
+ }
+
+ public void testSerialize() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes expected = builder.build();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testSerializePartial() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes expected = builder.buildPartial();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testEnumValues() {
+ assertEquals(
+ TestAllTypes.NestedEnum.BAR.getNumber(),
+ TestAllTypes.NestedEnum.BAR_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.BAZ.getNumber(),
+ TestAllTypes.NestedEnum.BAZ_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.FOO.getNumber(),
+ TestAllTypes.NestedEnum.FOO_VALUE);
+ }
+
+ public void testNonNestedExtensionInitialization() {
+ assertTrue(NonNestedExtension.nonNestedExtension
+ .getMessageDefaultInstance() instanceof MyNonNestedExtension);
+ assertEquals("nonNestedExtension",
+ NonNestedExtension.nonNestedExtension.getDescriptor().getName());
+ }
+
+ public void testNestedExtensionInitialization() {
+ assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
+ instanceof MessageToBeExtended);
+ assertEquals("recursiveExtension",
+ MyNestedExtension.recursiveExtension.getDescriptor().getName());
+ }
+
+
+ public void testBaseMessageOrBuilder() {
+ // Mostly just makes sure the base interface exists and has some methods.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message = builder.buildPartial();
+ TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
+ TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
+
+ assertEquals(
+ messageAsInterface.getDefaultBool(),
+ messageAsInterface.getDefaultBool());
+ assertEquals(
+ messageAsInterface.getOptionalDouble(),
+ messageAsInterface.getOptionalDouble());
+ }
+
+ public void testMessageOrBuilderGetters() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // single fields
+ assertSame(ForeignMessage.getDefaultInstance(),
+ builder.getOptionalForeignMessageOrBuilder());
+ ForeignMessage.Builder subBuilder =
+ builder.getOptionalForeignMessageBuilder();
+ assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
+
+ // repeated fields
+ ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
+ builder.addRepeatedForeignMessage(m0);
+ builder.addRepeatedForeignMessage(m1);
+ builder.addRepeatedForeignMessage(m2);
+ assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+ ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
+ ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
+ assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+
+ List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
+ builder.getRepeatedForeignMessageOrBuilderList();
+ assertSame(b0, messageOrBuilderList.get(0));
+ assertSame(b1, messageOrBuilderList.get(1));
+ assertSame(m2, messageOrBuilderList.get(2));
+ }
+
+ public void testGetFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("optional_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("optional_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+ .mergeFrom((Message) builder1.getField(fieldDescriptor));
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+ builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_message"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java
new file mode 100644
index 0000000000..9bc94eef1d
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringArrayListTest.java
@@ -0,0 +1,163 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link LazyStringArrayList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testJustStrings() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+
+ list.set(1, STRING_C);
+ assertSame(STRING_C, list.get(1));
+
+ list.remove(1);
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_C, list.get(1));
+ }
+
+ public void testJustByteString() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(BYTE_STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_B, list.getByteString(1));
+ assertSame(BYTE_STRING_C, list.getByteString(2));
+
+ list.remove(1);
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_C, list.getByteString(1));
+ }
+
+ public void testConversionBackAndForth() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ // String a should be the same because it was originally a string
+ assertSame(STRING_A, list.get(0));
+
+ // String b and c should be different because the string has to be computed
+ // from the ByteString
+ String bPrime = list.get(1);
+ assertNotSame(STRING_B, bPrime);
+ assertEquals(STRING_B, bPrime);
+ String cPrime = list.get(2);
+ assertNotSame(STRING_C, cPrime);
+ assertEquals(STRING_C, cPrime);
+
+ // String c and c should stay the same once cached.
+ assertSame(bPrime, list.get(1));
+ assertSame(cPrime, list.get(2));
+
+ // ByteString needs to be computed from string for both a and b
+ ByteString aPrimeByteString = list.getByteString(0);
+ assertEquals(BYTE_STRING_A, aPrimeByteString);
+ ByteString bPrimeByteString = list.getByteString(1);
+ assertNotSame(BYTE_STRING_B, bPrimeByteString);
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+
+ // Once cached, ByteString should stay cached.
+ assertSame(aPrimeByteString, list.getByteString(0));
+ assertSame(bPrimeByteString, list.getByteString(1));
+ }
+
+ public void testCopyConstructorCopiesByReference() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testListCopyConstructor() {
+ List<String> list1 = new ArrayList<String>();
+ list1.add(STRING_A);
+ list1.add(STRING_B);
+ list1.add(STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(STRING_B, list2.get(1));
+ assertSame(STRING_C, list2.get(2));
+ }
+
+ public void testAddAllCopiesByReferenceIfPossible() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList();
+ list2.addAll(list1);
+
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java
new file mode 100644
index 0000000000..e21e038993
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LazyStringEndToEndTest.java
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+
+/**
+ * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
+ * strings works correctly.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringEndToEndTest extends TestCase {
+
+ private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
+ ByteString.copyFrom(new byte[] {
+ 114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
+ 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+
+ private ByteString encodedTestAllTypes;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .addRepeatedString("baz")
+ .build()
+ .toByteString();
+ }
+
+ /**
+ * Tests that an invalid UTF8 string will roundtrip through a parse
+ * and serialization.
+ */
+ public void testParseAndSerialize() throws InvalidProtocolBufferException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ ByteString bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+
+ tV2.getOptionalString();
+ bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+ }
+
+ public void testParseAndWrite() throws IOException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
+ CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
+ tV2.writeTo(outputStream);
+ outputStream.flush();
+ assertEquals(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
+ ByteString.copyFrom(sink));
+ }
+
+ public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+ UnittestProto.TestAllTypes proto =
+ UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+ ByteString optional = proto.getOptionalStringBytes();
+ assertSame(optional, proto.getOptionalStringBytes());
+ assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+ ByteString repeated0 = proto.getRepeatedStringBytes(0);
+ ByteString repeated1 = proto.getRepeatedStringBytes(1);
+ assertSame(repeated0, proto.getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.getRepeatedStringBytes(1));
+ assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java
new file mode 100644
index 0000000000..b2dcc7e882
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/LiteralByteStringTest.java
@@ -0,0 +1,344 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Test {@link LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@link LiteralByteString}
+ * such as {@link BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+ protected static final String UTF_8 = "UTF-8";
+
+ protected String classUnderTest;
+ protected byte[] referenceBytes;
+ protected ByteString stringUnderTest;
+ protected int expectedHashCode;
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "LiteralByteString";
+ referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+ stringUnderTest = ByteString.copyFrom(referenceBytes);
+ expectedHashCode = 331161852;
+ }
+
+ protected String getActualClassName(Object object) {
+ String actualClassName = object.getClass().getName();
+ actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+ return actualClassName;
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = stringUnderTest.iterator();
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : stringUnderTest) {
+ stillEqual = (referenceBytes[j] == quantum);
+ ++j;
+ }
+ assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+ stringUnderTest.size());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ stringUnderTest.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ stringUnderTest.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+ stringUnderTest.copyTo(myBuffer);
+ assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+ Arrays.equals(referenceBytes, myBuffer.array()));
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ assertTrue(byteBuffer.remaining() == referenceBytes.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == referenceBytes.length);
+ assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ stringUnderTest.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo_mutating() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ for (int x = 0; x < len; ++x) {
+ b[off + x] = (byte) 0;
+ }
+ }
+
+ @Override
+ public void write(int b) {
+ // Purposefully left blank.
+ }
+ };
+
+ stringUnderTest.writeTo(os);
+ byte[] newBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+ Arrays.equals(referenceBytes, newBytes));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ stringUnderTest.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), stringUnderTest.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ ByteString.EMPTY, output.toByteString());
+
+ }
+
+ public void testHashCode() {
+ int hash = stringUnderTest.hashCode();
+ assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ stringUnderTest.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : referenceBytes) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ int stringSize = stringUnderTest.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = stringUnderTest.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+ assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+ stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+ assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+ ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java
new file mode 100644
index 0000000000..c8c95a87c7
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/MessageTest.java
@@ -0,0 +1,354 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+
+/**
+ * Misc. unit tests for message operations that apply to both generated
+ * and dynamic messages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class MessageTest extends TestCase {
+ // =================================================================
+ // Message-merging tests.
+
+ static final TestAllTypes MERGE_SOURCE =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .build();
+
+ static final TestAllTypes MERGE_DEST =
+ TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+ .addRepeatedString("qux")
+ .build();
+
+ static final String MERGE_RESULT_TEXT =
+ "optional_int32: 1\n" +
+ "optional_int64: 2\n" +
+ "optional_string: \"foo\"\n" +
+ "optional_foreign_message {\n" +
+ " c: 3\n" +
+ "}\n" +
+ "repeated_string: \"qux\"\n" +
+ "repeated_string: \"bar\"\n";
+
+ public void testMergeFrom() throws Exception {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(MERGE_SOURCE).build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /**
+ * Test merging a DynamicMessage into a GeneratedMessage. As long as they
+ * have the same descriptor, this should work, but it is an entirely different
+ * code path.
+ */
+ public void testMergeFromDynamic() throws Exception {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /** Test merging two DynamicMessages. */
+ public void testDynamicMergeFrom() throws Exception {
+ DynamicMessage result =
+ DynamicMessage.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ // =================================================================
+ // Required-field-related tests.
+
+ private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+ TestRequired.getDefaultInstance();
+ private static final TestRequired TEST_REQUIRED_INITIALIZED =
+ TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+ public void testRequired() throws Exception {
+ TestRequired.Builder builder = TestRequired.newBuilder();
+
+ assertFalse(builder.isInitialized());
+ builder.setA(1);
+ assertFalse(builder.isInitialized());
+ builder.setB(1);
+ assertFalse(builder.isInitialized());
+ builder.setC(1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredForeign() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredExtension() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamic() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("a"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("b"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("c"), 1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamicForeign() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertTrue(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testUninitializedException() throws Exception {
+ try {
+ TestRequired.newBuilder().build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequired message = TestRequired.newBuilder().buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testNestedUninitializedException() throws Exception {
+ try {
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testBuildNestedPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequiredForeign message =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testParseUnititialized() throws Exception {
+ try {
+ TestRequired.parseFrom(ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testParseNestedUnititialized() throws Exception {
+ ByteString data =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial().toByteString();
+
+ try {
+ TestRequiredForeign.parseFrom(data);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testDynamicUninitializedException() throws Exception {
+ try {
+ DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testDynamicBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ DynamicMessage message =
+ DynamicMessage.newBuilder(TestRequired.getDescriptor())
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testDynamicParseUnititialized() throws Exception {
+ try {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ /** Test reading unset repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNull() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 0);
+ }
+
+ /** Test reading repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+ TestAllTypes REPEATED_NESTED =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .build();
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 2);
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java
new file mode 100644
index 0000000000..68d70beca1
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/NestedBuildersTest.java
@@ -0,0 +1,186 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.Vehicle;
+import protobuf_unittest.Wheel;
+
+import junit.framework.TestCase;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Test cases that exercise end-to-end use cases involving
+ * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class NestedBuildersTest extends TestCase {
+
+ public void testMessagesAndBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(3);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(4);
+ vehicleBuilder.getEngineBuilder()
+ .setLiters(10);
+
+ Vehicle vehicle = vehicleBuilder.build();
+ assertEquals(4, vehicle.getWheelCount());
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(4, wheel.getRadius());
+ assertEquals(i + 1, wheel.getWidth());
+ }
+ assertEquals(10, vehicle.getEngine().getLiters());
+
+ for (int i = 0; i < 4; i++) {
+ vehicleBuilder.getWheelBuilder(i)
+ .setRadius(5)
+ .setWidth(i + 10);
+ }
+ vehicleBuilder.getEngineBuilder().setLiters(20);
+
+ vehicle = vehicleBuilder.build();
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(5, wheel.getRadius());
+ assertEquals(i + 10, wheel.getWidth());
+ }
+ assertEquals(20, vehicle.getEngine().getLiters());
+ assertTrue(vehicle.hasEngine());
+ }
+
+ public void testMessagesAreCached() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(3)
+ .setWidth(4);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(5)
+ .setWidth(6);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(7)
+ .setWidth(8);
+
+ // Make sure messages are cached.
+ List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Now get builders and check they didn't change.
+ for (int i = 0; i < wheels.size(); i++) {
+ vehicleBuilder.getWheel(i);
+ }
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Change just one
+ vehicleBuilder.getWheelBuilder(3)
+ .setRadius(20).setWidth(20);
+
+ // Now get wheels and check that only that one changed
+ for (int i = 0; i < wheels.size(); i++) {
+ if (i < 3) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ } else {
+ assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+ }
+ }
+
+ public void testRemove_WithNestedBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(2)
+ .setWidth(2);
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testRemove_WithNestedMessages() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(1)
+ .setWidth(1));
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(2)
+ .setWidth(2));
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testMerge() {
+ Vehicle vehicle1 = Vehicle.newBuilder()
+ .addWheel(Wheel.newBuilder().setRadius(1).build())
+ .addWheel(Wheel.newBuilder().setRadius(2).build())
+ .build();
+
+ Vehicle vehicle2 = Vehicle.newBuilder()
+ .mergeFrom(vehicle1)
+ .build();
+ // List should be the same -- no allocation
+ assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
+
+ Vehicle vehicle3 = vehicle1.toBuilder().build();
+ assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
+ }
+
+ public void testGettingBuilderMarksFieldAsHaving() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.getEngineBuilder();
+ Vehicle vehicle = vehicleBuilder.buildPartial();
+ assertTrue(vehicle.hasEngine());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java
new file mode 100644
index 0000000000..b35af689cd
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ParserTest.java
@@ -0,0 +1,278 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+ public void testGeneratedMessageParserSingleton() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertEquals(TestAllTypes.PARSER,
+ TestUtil.getAllSet().getParserForType());
+ }
+ }
+
+ private void assertRoundTripEquals(MessageLite message,
+ ExtensionRegistryLite registry)
+ throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ message.toByteString(), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data), registry));
+ }
+
+ private void assertRoundTripEquals(MessageLite message) throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length));
+ assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data)));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data)));
+ }
+
+ private void assertMessageEquals(MessageLite expected, MessageLite actual)
+ throws Exception {
+ if (expected instanceof Message) {
+ assertEquals(expected, actual);
+ } else {
+ assertEquals(expected.toByteString(), actual.toByteString());
+ }
+ }
+
+ private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+ byte[] result = new byte[offset + data.length + padding];
+ System.arraycopy(data, 0, result, offset, data.length);
+ return result;
+ }
+
+ public void testNormalMessage() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllSet());
+ }
+
+ public void testParsePartial() throws Exception {
+ Parser<TestRequired> parser = TestRequired.PARSER;
+ final String errorString =
+ "Should throw exceptions when the parsed message isn't initialized.";
+
+ // TestRequired.b and TestRequired.c are not set.
+ TestRequired partialMessage = TestRequired.newBuilder()
+ .setA(1).buildPartial();
+
+ // parsePartialFrom should pass.
+ byte[] data = partialMessage.toByteArray();
+ assertEquals(partialMessage, parser.parsePartialFrom(data));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ partialMessage.toByteString()));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ new ByteArrayInputStream(data)));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ CodedInputStream.newInstance(data)));
+
+ // parseFrom(ByteArray)
+ try {
+ parser.parseFrom(partialMessage.toByteArray());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(ByteString)
+ try {
+ parser.parseFrom(partialMessage.toByteString());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(InputStream)
+ try {
+ parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+
+ // parseFrom(CodedInputStream)
+ try {
+ parser.parseFrom(CodedInputStream.newInstance(
+ partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+ }
+
+ public void testParseDelimitedTo() throws Exception {
+ // Write normal Message.
+ TestAllTypes normalMessage = TestUtil.getAllSet();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ normalMessage.writeDelimitedTo(output);
+
+ InputStream input = new ByteArrayInputStream(output.toByteArray());
+ assertMessageEquals(
+ normalMessage,
+ normalMessage.getParserForType().parseDelimitedFrom(input));
+ }
+
+ public void testParseUnknownFields() throws Exception {
+ // All fields will be treated as unknown fields in emptyMessage.
+ TestEmptyMessage emptyMessage = TestEmptyMessage.PARSER.parseFrom(
+ TestUtil.getAllSet().toByteString());
+ assertEquals(
+ TestUtil.getAllSet().toByteString(),
+ emptyMessage.toByteString());
+ }
+
+ public void testOptimizeForSize() throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+ builder.setExtension(TestOptimizedForSize.testExtension, 56);
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+ TestOptimizedForSize message = builder.build();
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestOptimizeFor.registerAllExtensions(registry);
+
+ assertRoundTripEquals(message, registry);
+ }
+
+ /** Helper method for {@link #testParsingMerge()}.*/
+ private void assertMessageMerged(TestAllTypes allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ public void testParsingMerge() throws Exception {
+ // Build messages.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypes msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMerge.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestProto.registerAllExtensions(registry);
+ TestParsingMerge parsingMerge =
+ TestParsingMerge.PARSER.parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMerge.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMerge.repeatedExt));
+ }
+
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java
new file mode 100644
index 0000000000..3c1f5035b7
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringSubstringTest.java
@@ -0,0 +1,62 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+ ByteString sourceString = iter.next();
+ while (iter.hasNext()) {
+ sourceString = sourceString.concat(iter.next());
+ }
+
+ int from = 1130;
+ int to = sourceBytes.length - 5555;
+ stringUnderTest = sourceString.substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = -1259260680;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java
new file mode 100644
index 0000000000..8caeadd9a1
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/RopeByteStringTest.java
@@ -0,0 +1,84 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+ stringUnderTest = iter.next();
+ while (iter.hasNext()) {
+ stringUnderTest = stringUnderTest.concat(iter.next());
+ }
+ expectedHashCode = -1214197238;
+ }
+
+ public void testBalance() {
+ int numberOfPieces = 10000;
+ int pieceSize = 64;
+ byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+ // Build up a big ByteString from smaller pieces to force a rebalance
+ ByteString concatenated = ByteString.EMPTY;
+ for (int i = 0; i < numberOfPieces; ++i) {
+ concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+ }
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(concatenated));
+ assertTrue(classUnderTest + " underlying bytes must match after balancing",
+ Arrays.equals(testBytes, concatenated.toByteArray()));
+ ByteString testString = ByteString.copyFrom(testBytes);
+ assertTrue(classUnderTest + " balanced string must equal flat string",
+ concatenated.equals(testString));
+ assertTrue(classUnderTest + " flat string must equal balanced string",
+ testString.equals(concatenated));
+ assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+ testString.hashCode(), concatenated.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java
new file mode 100644
index 0000000000..4c7f751c0a
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/ServiceTest.java
@@ -0,0 +1,321 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestService;
+import protobuf_unittest.UnittestProto.FooRequest;
+import protobuf_unittest.UnittestProto.FooResponse;
+import protobuf_unittest.UnittestProto.BarRequest;
+import protobuf_unittest.UnittestProto.BarResponse;
+
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
+import org.easymock.IArgumentMatcher;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests services and stubs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ServiceTest extends TestCase {
+ private IMocksControl control;
+ private RpcController mockController;
+
+ private final Descriptors.MethodDescriptor fooDescriptor =
+ TestService.getDescriptor().getMethods().get(0);
+ private final Descriptors.MethodDescriptor barDescriptor =
+ TestService.getDescriptor().getMethods().get(1);
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ control = EasyMock.createStrictControl();
+ mockController = control.createMock(RpcController.class);
+ }
+
+ // =================================================================
+
+ /** Tests Service.callMethod(). */
+ public void testCallMethod() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<Message> fooCallback = new MockCallback<Message>();
+ MockCallback<Message> barCallback = new MockCallback<Message>();
+ TestService mockService = control.createMock(TestService.class);
+
+ mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
+ this.<FooResponse>wrapsCallback(fooCallback));
+ mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
+ this.<BarResponse>wrapsCallback(barCallback));
+ control.replay();
+
+ mockService.callMethod(fooDescriptor, mockController,
+ fooRequest, fooCallback);
+ mockService.callMethod(barDescriptor, mockController,
+ barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests Service.get{Request,Response}Prototype(). */
+ public void testGetPrototype() throws Exception {
+ TestService mockService = control.createMock(TestService.class);
+
+ assertSame(mockService.getRequestPrototype(fooDescriptor),
+ FooRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(fooDescriptor),
+ FooResponse.getDefaultInstance());
+ assertSame(mockService.getRequestPrototype(barDescriptor),
+ BarRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(barDescriptor),
+ BarResponse.getDefaultInstance());
+ }
+
+ /** Tests generated stubs. */
+ public void testStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
+ MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
+ RpcChannel mockChannel = control.createMock(RpcChannel.class);
+ TestService stub = TestService.newStub(mockChannel);
+
+ mockChannel.callMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(fooCallback));
+ mockChannel.callMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(barCallback));
+ control.replay();
+
+ stub.foo(mockController, fooRequest, fooCallback);
+ stub.bar(mockController, barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests generated blocking stubs. */
+ public void testBlockingStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ BlockingRpcChannel mockChannel =
+ control.createMock(BlockingRpcChannel.class);
+ TestService.BlockingInterface stub =
+ TestService.newBlockingStub(mockChannel);
+
+ FooResponse fooResponse = FooResponse.newBuilder().build();
+ BarResponse barResponse = BarResponse.newBuilder().build();
+
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+ control.replay();
+
+ assertSame(fooResponse, stub.foo(mockController, fooRequest));
+ assertSame(barResponse, stub.bar(mockController, barRequest));
+ control.verify();
+ }
+
+ public void testNewReflectiveService() {
+ ServiceWithNoOuter.Interface impl =
+ control.createMock(ServiceWithNoOuter.Interface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ Service service = ServiceWithNoOuter.newReflectiveService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+ RpcCallback<Message> callback = new RpcCallback<Message>() {
+ public void run(Message parameter) {
+ // No reason this should be run.
+ fail();
+ }
+ };
+ RpcCallback<TestAllTypes> specializedCallback =
+ RpcUtil.specializeCallback(callback);
+
+ impl.foo(EasyMock.same(controller), EasyMock.same(request),
+ EasyMock.same(specializedCallback));
+ EasyMock.expectLastCall();
+
+ control.replay();
+
+ service.callMethod(fooMethod, controller, request, callback);
+
+ control.verify();
+ }
+
+ public void testNewReflectiveBlockingService() throws ServiceException {
+ ServiceWithNoOuter.BlockingInterface impl =
+ control.createMock(ServiceWithNoOuter.BlockingInterface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ BlockingService service =
+ ServiceWithNoOuter.newReflectiveBlockingService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+
+ TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
+ EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
+ .andReturn(expectedResponse);
+
+ control.replay();
+
+ Message response =
+ service.callBlockingMethod(fooMethod, controller, request);
+ assertEquals(expectedResponse, response);
+
+ control.verify();
+ }
+
+ public void testNoGenericServices() throws Exception {
+ // Non-services should be usable.
+ UnittestNoGenericServices.TestMessage message =
+ UnittestNoGenericServices.TestMessage.newBuilder()
+ .setA(123)
+ .setExtension(UnittestNoGenericServices.testExtension, 456)
+ .build();
+ assertEquals(123, message.getA());
+ assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+ // Build a list of the class names nested in UnittestNoGenericServices.
+ String outerName = "google.protobuf.no_generic_services_test." +
+ "UnittestNoGenericServices";
+ Class<?> outerClass = Class.forName(outerName);
+
+ Set<String> innerClassNames = new HashSet<String>();
+ for (Class<?> innerClass : outerClass.getClasses()) {
+ String fullName = innerClass.getName();
+ // Figure out the unqualified name of the inner class.
+ // Note: Surprisingly, the full name of an inner class will be separated
+ // from the outer class name by a '$' rather than a '.'. This is not
+ // mentioned in the documentation for java.lang.Class. I don't want to
+ // make assumptions, so I'm just going to accept any character as the
+ // separator.
+ assertTrue(fullName.startsWith(outerName));
+
+ if (!Service.class.isAssignableFrom(innerClass) &&
+ !Message.class.isAssignableFrom(innerClass) &&
+ !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+ // Ignore any classes not generated by the base code generator.
+ continue;
+ }
+
+ innerClassNames.add(fullName.substring(outerName.length() + 1));
+ }
+
+ // No service class should have been generated.
+ assertTrue(innerClassNames.contains("TestMessage"));
+ assertTrue(innerClassNames.contains("TestEnum"));
+ assertFalse(innerClassNames.contains("TestService"));
+
+ // But descriptors are there.
+ FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+ assertEquals(1, file.getServices().size());
+ assertEquals("TestService", file.getServices().get(0).getName());
+ assertEquals(1, file.getServices().get(0).getMethods().size());
+ assertEquals("Foo",
+ file.getServices().get(0).getMethods().get(0).getName());
+ }
+
+ // =================================================================
+
+ /**
+ * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c)
+ * matches a callback if calling that callback causes c to be called.
+ * In other words, c wraps the given callback.
+ */
+ private <Type extends Message> RpcCallback<Type> wrapsCallback(
+ MockCallback<?> callback) {
+ EasyMock.reportMatcher(new WrapsCallback(callback));
+ return null;
+ }
+
+ /** The parameter to wrapsCallback() must be a MockCallback. */
+ private static class MockCallback<Type extends Message>
+ implements RpcCallback<Type> {
+ private boolean called = false;
+
+ public boolean isCalled() { return called; }
+
+ public void reset() { called = false; }
+ public void run(Type message) { called = true; }
+ }
+
+ /** Implementation of the wrapsCallback() argument matcher. */
+ private static class WrapsCallback implements IArgumentMatcher {
+ private MockCallback<?> callback;
+
+ public WrapsCallback(MockCallback<?> callback) {
+ this.callback = callback;
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean matches(Object actual) {
+ if (!(actual instanceof RpcCallback)) {
+ return false;
+ }
+ RpcCallback actualCallback = (RpcCallback)actual;
+
+ callback.reset();
+ actualCallback.run(null);
+ return callback.isCalled();
+ }
+
+ public void appendTo(StringBuffer buffer) {
+ buffer.append("wrapsCallback(mockCallback)");
+ }
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java
new file mode 100644
index 0000000000..5086732295
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestBadIdentifiers.java
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when
+ * compiling protocol buffers that have names that would otherwise conflict
+ * if not fully qualified (like @Deprecated and @Override).
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class TestBadIdentifiers extends TestCase {
+
+ public void testCompilation() {
+ // If this compiles, it means the generation was correct.
+ TestBadIdentifiersProto.Deprecated.newBuilder();
+ TestBadIdentifiersProto.Override.newBuilder();
+ }
+
+ public void testGetDescriptor() {
+ Descriptors.FileDescriptor fileDescriptor =
+ TestBadIdentifiersProto.getDescriptor();
+ String descriptorField = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptorForType();
+ String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+ .NestedDescriptor.getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+ .Descriptor.NestedDescriptor.getDefaultInstance()
+ .getDescriptorForType();
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java
new file mode 100644
index 0000000000..a92348303e
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TestUtil.java
@@ -0,0 +1,3068 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto;
+
+// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
+// import static protobuf_unittest.UnittestProto.*;
+import static protobuf_unittest.UnittestProto.defaultInt32Extension;
+import static protobuf_unittest.UnittestProto.defaultInt64Extension;
+import static protobuf_unittest.UnittestProto.defaultUint32Extension;
+import static protobuf_unittest.UnittestProto.defaultUint64Extension;
+import static protobuf_unittest.UnittestProto.defaultSint32Extension;
+import static protobuf_unittest.UnittestProto.defaultSint64Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultFloatExtension;
+import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
+import static protobuf_unittest.UnittestProto.defaultBoolExtension;
+import static protobuf_unittest.UnittestProto.defaultStringExtension;
+import static protobuf_unittest.UnittestProto.defaultBytesExtension;
+import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
+import static protobuf_unittest.UnittestProto.defaultCordExtension;
+
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+import static protobuf_unittest.UnittestProto.optionalUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalUint64Extension;
+import static protobuf_unittest.UnittestProto.optionalSint32Extension;
+import static protobuf_unittest.UnittestProto.optionalSint64Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalFloatExtension;
+import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
+import static protobuf_unittest.UnittestProto.optionalBoolExtension;
+import static protobuf_unittest.UnittestProto.optionalStringExtension;
+import static protobuf_unittest.UnittestProto.optionalBytesExtension;
+import static protobuf_unittest.UnittestProto.optionalGroupExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
+
+import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
+import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
+import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
+import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringExtension;
+import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
+import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
+import static protobuf_unittest.UnittestProto.repeatedCordExtension;
+
+import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
+
+import static protobuf_unittest.UnittestProto.packedInt32Extension;
+import static protobuf_unittest.UnittestProto.packedInt64Extension;
+import static protobuf_unittest.UnittestProto.packedUint32Extension;
+import static protobuf_unittest.UnittestProto.packedUint64Extension;
+import static protobuf_unittest.UnittestProto.packedSint32Extension;
+import static protobuf_unittest.UnittestProto.packedSint64Extension;
+import static protobuf_unittest.UnittestProto.packedFixed32Extension;
+import static protobuf_unittest.UnittestProto.packedFixed64Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.packedFloatExtension;
+import static protobuf_unittest.UnittestProto.packedDoubleExtension;
+import static protobuf_unittest.UnittestProto.packedBoolExtension;
+import static protobuf_unittest.UnittestProto.packedEnumExtension;
+
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
+
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+/**
+ * Contains methods for setting all fields of {@code TestAllTypes} to
+ * some values as well as checking that all the fields are set to those values.
+ * These are useful for testing various protocol message features, e.g.
+ * set all fields of a message, serialize it, parse it, and check that all
+ * fields are set.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TestUtil {
+ private TestUtil() {}
+
+ /** Helper to convert a String to ByteString. */
+ static ByteString toBytes(String str) {
+ try {
+ return ByteString.copyFrom(str.getBytes("UTF-8"));
+ } catch(java.io.UnsupportedEncodingException e) {
+ throw new RuntimeException("UTF-8 not supported.", e);
+ }
+ }
+
+ /**
+ * Get a {@code TestAllTypes} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes getAllSet() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder.build();
+ }
+
+ /**
+ * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes.Builder getAllSetBuilder() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
+ * Get a {@code TestAllExtensions} with all fields set as they would be by
+ * {@link #setAllExtensions(TestAllExtensions.Builder)}.
+ */
+ public static TestAllExtensions getAllExtensionsSet() {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestPackedTypes getPackedSet() {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ setPackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestUnpackedTypes getUnpackedSet() {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ setUnpackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensions getPackedExtensionsSet() {
+ TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}.
+ */
+ public static void setAllFields(TestAllTypes.Builder message) {
+ message.setOptionalInt32 (101);
+ message.setOptionalInt64 (102);
+ message.setOptionalUint32 (103);
+ message.setOptionalUint64 (104);
+ message.setOptionalSint32 (105);
+ message.setOptionalSint64 (106);
+ message.setOptionalFixed32 (107);
+ message.setOptionalFixed64 (108);
+ message.setOptionalSfixed32(109);
+ message.setOptionalSfixed64(110);
+ message.setOptionalFloat (111);
+ message.setOptionalDouble (112);
+ message.setOptionalBool (true);
+ message.setOptionalString ("115");
+ message.setOptionalBytes (toBytes("116"));
+
+ message.setOptionalGroup(
+ TestAllTypes.OptionalGroup.newBuilder().setA(117).build());
+ message.setOptionalNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setOptionalImportMessage(
+ ImportMessage.newBuilder().setD(120).build());
+ message.setOptionalPublicImportMessage(
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setOptionalLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.setOptionalStringPiece("124");
+ message.setOptionalCord("125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedInt32 (201);
+ message.addRepeatedInt64 (202);
+ message.addRepeatedUint32 (203);
+ message.addRepeatedUint64 (204);
+ message.addRepeatedSint32 (205);
+ message.addRepeatedSint64 (206);
+ message.addRepeatedFixed32 (207);
+ message.addRepeatedFixed64 (208);
+ message.addRepeatedSfixed32(209);
+ message.addRepeatedSfixed64(210);
+ message.addRepeatedFloat (211);
+ message.addRepeatedDouble (212);
+ message.addRepeatedBool (true);
+ message.addRepeatedString ("215");
+ message.addRepeatedBytes (toBytes("216"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(217).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(220).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR);
+
+ message.addRepeatedStringPiece("224");
+ message.addRepeatedCord("225");
+
+ // Add a second one of each field.
+ message.addRepeatedInt32 (301);
+ message.addRepeatedInt64 (302);
+ message.addRepeatedUint32 (303);
+ message.addRepeatedUint64 (304);
+ message.addRepeatedSint32 (305);
+ message.addRepeatedSint64 (306);
+ message.addRepeatedFixed32 (307);
+ message.addRepeatedFixed64 (308);
+ message.addRepeatedSfixed32(309);
+ message.addRepeatedSfixed64(310);
+ message.addRepeatedFloat (311);
+ message.addRepeatedDouble (312);
+ message.addRepeatedBool (false);
+ message.addRepeatedString ("315");
+ message.addRepeatedBytes (toBytes("316"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(317).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(320).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.addRepeatedStringPiece("324");
+ message.addRepeatedCord("325");
+
+ // -----------------------------------------------------------------
+
+ message.setDefaultInt32 (401);
+ message.setDefaultInt64 (402);
+ message.setDefaultUint32 (403);
+ message.setDefaultUint64 (404);
+ message.setDefaultSint32 (405);
+ message.setDefaultSint64 (406);
+ message.setDefaultFixed32 (407);
+ message.setDefaultFixed64 (408);
+ message.setDefaultSfixed32(409);
+ message.setDefaultSfixed64(410);
+ message.setDefaultFloat (411);
+ message.setDefaultDouble (412);
+ message.setDefaultBool (false);
+ message.setDefaultString ("415");
+ message.setDefaultBytes (toBytes("416"));
+
+ message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
+ message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
+ message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
+
+ message.setDefaultStringPiece("424");
+ message.setDefaultCord("425");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}.
+ */
+ public static void modifyRepeatedFields(TestAllTypes.Builder message) {
+ message.setRepeatedInt32 (1, 501);
+ message.setRepeatedInt64 (1, 502);
+ message.setRepeatedUint32 (1, 503);
+ message.setRepeatedUint64 (1, 504);
+ message.setRepeatedSint32 (1, 505);
+ message.setRepeatedSint64 (1, 506);
+ message.setRepeatedFixed32 (1, 507);
+ message.setRepeatedFixed64 (1, 508);
+ message.setRepeatedSfixed32(1, 509);
+ message.setRepeatedSfixed64(1, 510);
+ message.setRepeatedFloat (1, 511);
+ message.setRepeatedDouble (1, 512);
+ message.setRepeatedBool (1, true);
+ message.setRepeatedString (1, "515");
+ message.setRepeatedBytes (1, toBytes("516"));
+
+ message.setRepeatedGroup(1,
+ TestAllTypes.RepeatedGroup.newBuilder().setA(517).build());
+ message.setRepeatedNestedMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setRepeatedForeignMessage(1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setRepeatedImportMessage(1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setRepeatedLazyMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
+ message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
+ message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO);
+
+ message.setRepeatedStringPiece(1, "524");
+ message.setRepeatedCord(1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}.
+ */
+ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
+ Assert.assertTrue(message.hasOptionalInt32 ());
+ Assert.assertTrue(message.hasOptionalInt64 ());
+ Assert.assertTrue(message.hasOptionalUint32 ());
+ Assert.assertTrue(message.hasOptionalUint64 ());
+ Assert.assertTrue(message.hasOptionalSint32 ());
+ Assert.assertTrue(message.hasOptionalSint64 ());
+ Assert.assertTrue(message.hasOptionalFixed32 ());
+ Assert.assertTrue(message.hasOptionalFixed64 ());
+ Assert.assertTrue(message.hasOptionalSfixed32());
+ Assert.assertTrue(message.hasOptionalSfixed64());
+ Assert.assertTrue(message.hasOptionalFloat ());
+ Assert.assertTrue(message.hasOptionalDouble ());
+ Assert.assertTrue(message.hasOptionalBool ());
+ Assert.assertTrue(message.hasOptionalString ());
+ Assert.assertTrue(message.hasOptionalBytes ());
+
+ Assert.assertTrue(message.hasOptionalGroup ());
+ Assert.assertTrue(message.hasOptionalNestedMessage ());
+ Assert.assertTrue(message.hasOptionalForeignMessage());
+ Assert.assertTrue(message.hasOptionalImportMessage ());
+
+ Assert.assertTrue(message.getOptionalGroup ().hasA());
+ Assert.assertTrue(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertTrue(message.getOptionalForeignMessage().hasC());
+ Assert.assertTrue(message.getOptionalImportMessage ().hasD());
+
+ Assert.assertTrue(message.hasOptionalNestedEnum ());
+ Assert.assertTrue(message.hasOptionalForeignEnum());
+ Assert.assertTrue(message.hasOptionalImportEnum ());
+
+ Assert.assertTrue(message.hasOptionalStringPiece());
+ Assert.assertTrue(message.hasOptionalCord());
+
+ Assert.assertEquals(101 , message.getOptionalInt32 ());
+ Assert.assertEquals(102 , message.getOptionalInt64 ());
+ Assert.assertEquals(103 , message.getOptionalUint32 ());
+ Assert.assertEquals(104 , message.getOptionalUint64 ());
+ Assert.assertEquals(105 , message.getOptionalSint32 ());
+ Assert.assertEquals(106 , message.getOptionalSint64 ());
+ Assert.assertEquals(107 , message.getOptionalFixed32 ());
+ Assert.assertEquals(108 , message.getOptionalFixed64 ());
+ Assert.assertEquals(109 , message.getOptionalSfixed32());
+ Assert.assertEquals(110 , message.getOptionalSfixed64());
+ Assert.assertEquals(111 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(112 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(true , message.getOptionalBool ());
+ Assert.assertEquals("115", message.getOptionalString ());
+ Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
+
+ Assert.assertEquals(117, message.getOptionalGroup ().getA());
+ Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(119, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
+
+ Assert.assertEquals("124", message.getOptionalStringPiece());
+ Assert.assertEquals("125", message.getOptionalCord());
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202 , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204 , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206 , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208 , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210 , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211 , message.getRepeatedFloat (0), 0.0);
+ Assert.assertEquals(212 , message.getRepeatedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ Assert.assertEquals(301 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(302 , message.getRepeatedInt64 (1));
+ Assert.assertEquals(303 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(304 , message.getRepeatedUint64 (1));
+ Assert.assertEquals(305 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(306 , message.getRepeatedSint64 (1));
+ Assert.assertEquals(307 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(308 , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(309 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(310 , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(311 , message.getRepeatedFloat (1), 0.0);
+ Assert.assertEquals(312 , message.getRepeatedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getRepeatedBool (1));
+ Assert.assertEquals("315", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(317, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("324", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("325", message.getRepeatedCord(1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasDefaultInt32 ());
+ Assert.assertTrue(message.hasDefaultInt64 ());
+ Assert.assertTrue(message.hasDefaultUint32 ());
+ Assert.assertTrue(message.hasDefaultUint64 ());
+ Assert.assertTrue(message.hasDefaultSint32 ());
+ Assert.assertTrue(message.hasDefaultSint64 ());
+ Assert.assertTrue(message.hasDefaultFixed32 ());
+ Assert.assertTrue(message.hasDefaultFixed64 ());
+ Assert.assertTrue(message.hasDefaultSfixed32());
+ Assert.assertTrue(message.hasDefaultSfixed64());
+ Assert.assertTrue(message.hasDefaultFloat ());
+ Assert.assertTrue(message.hasDefaultDouble ());
+ Assert.assertTrue(message.hasDefaultBool ());
+ Assert.assertTrue(message.hasDefaultString ());
+ Assert.assertTrue(message.hasDefaultBytes ());
+
+ Assert.assertTrue(message.hasDefaultNestedEnum ());
+ Assert.assertTrue(message.hasDefaultForeignEnum());
+ Assert.assertTrue(message.hasDefaultImportEnum ());
+
+ Assert.assertTrue(message.hasDefaultStringPiece());
+ Assert.assertTrue(message.hasDefaultCord());
+
+ Assert.assertEquals(401 , message.getDefaultInt32 ());
+ Assert.assertEquals(402 , message.getDefaultInt64 ());
+ Assert.assertEquals(403 , message.getDefaultUint32 ());
+ Assert.assertEquals(404 , message.getDefaultUint64 ());
+ Assert.assertEquals(405 , message.getDefaultSint32 ());
+ Assert.assertEquals(406 , message.getDefaultSint64 ());
+ Assert.assertEquals(407 , message.getDefaultFixed32 ());
+ Assert.assertEquals(408 , message.getDefaultFixed64 ());
+ Assert.assertEquals(409 , message.getDefaultSfixed32());
+ Assert.assertEquals(410 , message.getDefaultSfixed64());
+ Assert.assertEquals(411 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals(412 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(false, message.getDefaultBool ());
+ Assert.assertEquals("415", message.getDefaultString ());
+ Assert.assertEquals(toBytes("416"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
+
+ Assert.assertEquals("424", message.getDefaultStringPiece());
+ Assert.assertEquals("425", message.getDefaultCord());
+ }
+
+ // -------------------------------------------------------------------
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values.
+ */
+ public static void assertClear(TestAllTypesOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasOptionalInt32 ());
+ Assert.assertFalse(message.hasOptionalInt64 ());
+ Assert.assertFalse(message.hasOptionalUint32 ());
+ Assert.assertFalse(message.hasOptionalUint64 ());
+ Assert.assertFalse(message.hasOptionalSint32 ());
+ Assert.assertFalse(message.hasOptionalSint64 ());
+ Assert.assertFalse(message.hasOptionalFixed32 ());
+ Assert.assertFalse(message.hasOptionalFixed64 ());
+ Assert.assertFalse(message.hasOptionalSfixed32());
+ Assert.assertFalse(message.hasOptionalSfixed64());
+ Assert.assertFalse(message.hasOptionalFloat ());
+ Assert.assertFalse(message.hasOptionalDouble ());
+ Assert.assertFalse(message.hasOptionalBool ());
+ Assert.assertFalse(message.hasOptionalString ());
+ Assert.assertFalse(message.hasOptionalBytes ());
+
+ Assert.assertFalse(message.hasOptionalGroup ());
+ Assert.assertFalse(message.hasOptionalNestedMessage ());
+ Assert.assertFalse(message.hasOptionalForeignMessage());
+ Assert.assertFalse(message.hasOptionalImportMessage ());
+
+ Assert.assertFalse(message.hasOptionalNestedEnum ());
+ Assert.assertFalse(message.hasOptionalForeignEnum());
+ Assert.assertFalse(message.hasOptionalImportEnum ());
+
+ Assert.assertFalse(message.hasOptionalStringPiece());
+ Assert.assertFalse(message.hasOptionalCord());
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getOptionalInt32 ());
+ Assert.assertEquals(0 , message.getOptionalInt64 ());
+ Assert.assertEquals(0 , message.getOptionalUint32 ());
+ Assert.assertEquals(0 , message.getOptionalUint64 ());
+ Assert.assertEquals(0 , message.getOptionalSint32 ());
+ Assert.assertEquals(0 , message.getOptionalSint64 ());
+ Assert.assertEquals(0 , message.getOptionalFixed32 ());
+ Assert.assertEquals(0 , message.getOptionalFixed64 ());
+ Assert.assertEquals(0 , message.getOptionalSfixed32());
+ Assert.assertEquals(0 , message.getOptionalSfixed64());
+ Assert.assertEquals(0 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(0 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(false, message.getOptionalBool ());
+ Assert.assertEquals("" , message.getOptionalString ());
+ Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getOptionalGroup ().hasA());
+ Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertFalse(message.getOptionalForeignMessage ().hasC());
+ Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+ Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+ Assert.assertFalse(message.getOptionalLazyMessage ().hasBb());
+
+ Assert.assertEquals(0, message.getOptionalGroup ().getA());
+ Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(0, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb());
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum());
+
+ Assert.assertEquals("", message.getOptionalStringPiece());
+ Assert.assertEquals("", message.getOptionalCord());
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedInt32Count ());
+ Assert.assertEquals(0, message.getRepeatedInt64Count ());
+ Assert.assertEquals(0, message.getRepeatedUint32Count ());
+ Assert.assertEquals(0, message.getRepeatedUint64Count ());
+ Assert.assertEquals(0, message.getRepeatedSint32Count ());
+ Assert.assertEquals(0, message.getRepeatedSint64Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(0, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(0, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(0, message.getRepeatedFloatCount ());
+ Assert.assertEquals(0, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(0, message.getRepeatedBoolCount ());
+ Assert.assertEquals(0, message.getRepeatedStringCount ());
+ Assert.assertEquals(0, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(0, message.getRepeatedGroupCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(0, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(0, message.getRepeatedCordCount());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasDefaultInt32 ());
+ Assert.assertFalse(message.hasDefaultInt64 ());
+ Assert.assertFalse(message.hasDefaultUint32 ());
+ Assert.assertFalse(message.hasDefaultUint64 ());
+ Assert.assertFalse(message.hasDefaultSint32 ());
+ Assert.assertFalse(message.hasDefaultSint64 ());
+ Assert.assertFalse(message.hasDefaultFixed32 ());
+ Assert.assertFalse(message.hasDefaultFixed64 ());
+ Assert.assertFalse(message.hasDefaultSfixed32());
+ Assert.assertFalse(message.hasDefaultSfixed64());
+ Assert.assertFalse(message.hasDefaultFloat ());
+ Assert.assertFalse(message.hasDefaultDouble ());
+ Assert.assertFalse(message.hasDefaultBool ());
+ Assert.assertFalse(message.hasDefaultString ());
+ Assert.assertFalse(message.hasDefaultBytes ());
+
+ Assert.assertFalse(message.hasDefaultNestedEnum ());
+ Assert.assertFalse(message.hasDefaultForeignEnum());
+ Assert.assertFalse(message.hasDefaultImportEnum ());
+
+ Assert.assertFalse(message.hasDefaultStringPiece());
+ Assert.assertFalse(message.hasDefaultCord());
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getDefaultInt32 ());
+ Assert.assertEquals( 42 , message.getDefaultInt64 ());
+ Assert.assertEquals( 43 , message.getDefaultUint32 ());
+ Assert.assertEquals( 44 , message.getDefaultUint64 ());
+ Assert.assertEquals(-45 , message.getDefaultSint32 ());
+ Assert.assertEquals( 46 , message.getDefaultSint64 ());
+ Assert.assertEquals( 47 , message.getDefaultFixed32 ());
+ Assert.assertEquals( 48 , message.getDefaultFixed64 ());
+ Assert.assertEquals( 49 , message.getDefaultSfixed32());
+ Assert.assertEquals(-50 , message.getDefaultSfixed64());
+ Assert.assertEquals( 51.5 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals( 52e3 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(true , message.getDefaultBool ());
+ Assert.assertEquals("hello", message.getDefaultString ());
+ Assert.assertEquals(toBytes("world"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
+
+ Assert.assertEquals("abc", message.getDefaultStringPiece());
+ Assert.assertEquals("123", message.getDefaultCord());
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}
+ * followed by {@code modifyRepeatedFields}.
+ */
+ public static void assertRepeatedFieldsModified(
+ TestAllTypesOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202L , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204L , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206L , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208L , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210L , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211F , message.getRepeatedFloat (0));
+ Assert.assertEquals(212D , message.getRepeatedDouble (0));
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ // Actually verify the second (modified) elements now.
+ Assert.assertEquals(501 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(502L , message.getRepeatedInt64 (1));
+ Assert.assertEquals(503 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(504L , message.getRepeatedUint64 (1));
+ Assert.assertEquals(505 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(506L , message.getRepeatedSint64 (1));
+ Assert.assertEquals(507 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(508L , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(509 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(510L , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(511F , message.getRepeatedFloat (1));
+ Assert.assertEquals(512D , message.getRepeatedDouble (1));
+ Assert.assertEquals(true , message.getRepeatedBool (1));
+ Assert.assertEquals("515", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(517, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("524", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("525", message.getRepeatedCord(1));
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value.
+ */
+ public static void setPackedFields(TestPackedTypes.Builder message) {
+ message.addPackedInt32 (601);
+ message.addPackedInt64 (602);
+ message.addPackedUint32 (603);
+ message.addPackedUint64 (604);
+ message.addPackedSint32 (605);
+ message.addPackedSint64 (606);
+ message.addPackedFixed32 (607);
+ message.addPackedFixed64 (608);
+ message.addPackedSfixed32(609);
+ message.addPackedSfixed64(610);
+ message.addPackedFloat (611);
+ message.addPackedDouble (612);
+ message.addPackedBool (true);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addPackedInt32 (701);
+ message.addPackedInt64 (702);
+ message.addPackedUint32 (703);
+ message.addPackedUint64 (704);
+ message.addPackedSint32 (705);
+ message.addPackedSint64 (706);
+ message.addPackedFixed32 (707);
+ message.addPackedFixed64 (708);
+ message.addPackedSfixed32(709);
+ message.addPackedSfixed64(710);
+ message.addPackedFloat (711);
+ message.addPackedDouble (712);
+ message.addPackedBool (false);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value. Must correspond with
+ * the values applied by {@code setPackedFields}.
+ */
+ public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+ message.addUnpackedInt32 (601);
+ message.addUnpackedInt64 (602);
+ message.addUnpackedUint32 (603);
+ message.addUnpackedUint64 (604);
+ message.addUnpackedSint32 (605);
+ message.addUnpackedSint64 (606);
+ message.addUnpackedFixed32 (607);
+ message.addUnpackedFixed64 (608);
+ message.addUnpackedSfixed32(609);
+ message.addUnpackedSfixed64(610);
+ message.addUnpackedFloat (611);
+ message.addUnpackedDouble (612);
+ message.addUnpackedBool (true);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addUnpackedInt32 (701);
+ message.addUnpackedInt64 (702);
+ message.addUnpackedUint32 (703);
+ message.addUnpackedUint64 (704);
+ message.addUnpackedSint32 (705);
+ message.addUnpackedSint64 (706);
+ message.addUnpackedFixed32 (707);
+ message.addUnpackedFixed64 (708);
+ message.addUnpackedSfixed32(709);
+ message.addUnpackedSfixed64(710);
+ message.addUnpackedFloat (711);
+ message.addUnpackedDouble (712);
+ message.addUnpackedBool (false);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setPackedFields}.
+ */
+ public static void assertPackedFieldsSet(TestPackedTypes message) {
+ Assert.assertEquals(2, message.getPackedInt32Count ());
+ Assert.assertEquals(2, message.getPackedInt64Count ());
+ Assert.assertEquals(2, message.getPackedUint32Count ());
+ Assert.assertEquals(2, message.getPackedUint64Count ());
+ Assert.assertEquals(2, message.getPackedSint32Count ());
+ Assert.assertEquals(2, message.getPackedSint64Count ());
+ Assert.assertEquals(2, message.getPackedFixed32Count ());
+ Assert.assertEquals(2, message.getPackedFixed64Count ());
+ Assert.assertEquals(2, message.getPackedSfixed32Count());
+ Assert.assertEquals(2, message.getPackedSfixed64Count());
+ Assert.assertEquals(2, message.getPackedFloatCount ());
+ Assert.assertEquals(2, message.getPackedDoubleCount ());
+ Assert.assertEquals(2, message.getPackedBoolCount ());
+ Assert.assertEquals(2, message.getPackedEnumCount ());
+ Assert.assertEquals(601 , message.getPackedInt32 (0));
+ Assert.assertEquals(602 , message.getPackedInt64 (0));
+ Assert.assertEquals(603 , message.getPackedUint32 (0));
+ Assert.assertEquals(604 , message.getPackedUint64 (0));
+ Assert.assertEquals(605 , message.getPackedSint32 (0));
+ Assert.assertEquals(606 , message.getPackedSint64 (0));
+ Assert.assertEquals(607 , message.getPackedFixed32 (0));
+ Assert.assertEquals(608 , message.getPackedFixed64 (0));
+ Assert.assertEquals(609 , message.getPackedSfixed32(0));
+ Assert.assertEquals(610 , message.getPackedSfixed64(0));
+ Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getPackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+ Assert.assertEquals(701 , message.getPackedInt32 (1));
+ Assert.assertEquals(702 , message.getPackedInt64 (1));
+ Assert.assertEquals(703 , message.getPackedUint32 (1));
+ Assert.assertEquals(704 , message.getPackedUint64 (1));
+ Assert.assertEquals(705 , message.getPackedSint32 (1));
+ Assert.assertEquals(706 , message.getPackedSint64 (1));
+ Assert.assertEquals(707 , message.getPackedFixed32 (1));
+ Assert.assertEquals(708 , message.getPackedFixed64 (1));
+ Assert.assertEquals(709 , message.getPackedSfixed32(1));
+ Assert.assertEquals(710 , message.getPackedSfixed64(1));
+ Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getPackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+ */
+ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+ Assert.assertEquals(2, message.getUnpackedInt32Count ());
+ Assert.assertEquals(2, message.getUnpackedInt64Count ());
+ Assert.assertEquals(2, message.getUnpackedUint32Count ());
+ Assert.assertEquals(2, message.getUnpackedUint64Count ());
+ Assert.assertEquals(2, message.getUnpackedSint32Count ());
+ Assert.assertEquals(2, message.getUnpackedSint64Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+ Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+ Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+ Assert.assertEquals(2, message.getUnpackedFloatCount ());
+ Assert.assertEquals(2, message.getUnpackedDoubleCount ());
+ Assert.assertEquals(2, message.getUnpackedBoolCount ());
+ Assert.assertEquals(2, message.getUnpackedEnumCount ());
+ Assert.assertEquals(601 , message.getUnpackedInt32 (0));
+ Assert.assertEquals(602 , message.getUnpackedInt64 (0));
+ Assert.assertEquals(603 , message.getUnpackedUint32 (0));
+ Assert.assertEquals(604 , message.getUnpackedUint64 (0));
+ Assert.assertEquals(605 , message.getUnpackedSint32 (0));
+ Assert.assertEquals(606 , message.getUnpackedSint64 (0));
+ Assert.assertEquals(607 , message.getUnpackedFixed32 (0));
+ Assert.assertEquals(608 , message.getUnpackedFixed64 (0));
+ Assert.assertEquals(609 , message.getUnpackedSfixed32(0));
+ Assert.assertEquals(610 , message.getUnpackedSfixed64(0));
+ Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getUnpackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+ Assert.assertEquals(701 , message.getUnpackedInt32 (1));
+ Assert.assertEquals(702 , message.getUnpackedInt64 (1));
+ Assert.assertEquals(703 , message.getUnpackedUint32 (1));
+ Assert.assertEquals(704 , message.getUnpackedUint64 (1));
+ Assert.assertEquals(705 , message.getUnpackedSint32 (1));
+ Assert.assertEquals(706 , message.getUnpackedSint64 (1));
+ Assert.assertEquals(707 , message.getUnpackedFixed32 (1));
+ Assert.assertEquals(708 , message.getUnpackedFixed64 (1));
+ Assert.assertEquals(709 , message.getUnpackedSfixed32(1));
+ Assert.assertEquals(710 , message.getUnpackedSfixed64(1));
+ Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getUnpackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+ }
+
+ // ===================================================================
+ // Like above, but for extensions
+
+ // Java gets confused with things like assertEquals(int, Integer): it can't
+ // decide whether to call assertEquals(int, int) or assertEquals(Object,
+ // Object). So we define these methods to help it.
+ private static void assertEqualsExactType(int a, int b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(long a, long b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(float a, float b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(double a, double b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(boolean a, boolean b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(String a, String b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ByteString a, ByteString b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
+ TestAllTypes.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ /**
+ * Get an unmodifiable {@link ExtensionRegistry} containing all the
+ * extensions of {@code TestAllExtensions}.
+ */
+ public static ExtensionRegistry getExtensionRegistry() {
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ registerAllExtensions(registry);
+ return registry.getUnmodifiable();
+ }
+
+
+ /**
+ * Register all of {@code TestAllExtensions}'s extensions with the
+ * given {@link ExtensionRegistry}.
+ */
+ public static void registerAllExtensions(ExtensionRegistry registry) {
+ UnittestProto.registerAllExtensions(registry);
+ }
+
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensions.Builder message) {
+ message.setExtension(optionalInt32Extension , 101);
+ message.setExtension(optionalInt64Extension , 102L);
+ message.setExtension(optionalUint32Extension , 103);
+ message.setExtension(optionalUint64Extension , 104L);
+ message.setExtension(optionalSint32Extension , 105);
+ message.setExtension(optionalSint64Extension , 106L);
+ message.setExtension(optionalFixed32Extension , 107);
+ message.setExtension(optionalFixed64Extension , 108L);
+ message.setExtension(optionalSfixed32Extension, 109);
+ message.setExtension(optionalSfixed64Extension, 110L);
+ message.setExtension(optionalFloatExtension , 111F);
+ message.setExtension(optionalDoubleExtension , 112D);
+ message.setExtension(optionalBoolExtension , true);
+ message.setExtension(optionalStringExtension , "115");
+ message.setExtension(optionalBytesExtension , toBytes("116"));
+
+ message.setExtension(optionalGroupExtension,
+ OptionalGroup_extension.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtension,
+ ImportMessage.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtension,
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.setExtension(optionalStringPieceExtension, "124");
+ message.setExtension(optionalCordExtension, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32Extension , 201);
+ message.addExtension(repeatedInt64Extension , 202L);
+ message.addExtension(repeatedUint32Extension , 203);
+ message.addExtension(repeatedUint64Extension , 204L);
+ message.addExtension(repeatedSint32Extension , 205);
+ message.addExtension(repeatedSint64Extension , 206L);
+ message.addExtension(repeatedFixed32Extension , 207);
+ message.addExtension(repeatedFixed64Extension , 208L);
+ message.addExtension(repeatedSfixed32Extension, 209);
+ message.addExtension(repeatedSfixed64Extension, 210L);
+ message.addExtension(repeatedFloatExtension , 211F);
+ message.addExtension(repeatedDoubleExtension , 212D);
+ message.addExtension(repeatedBoolExtension , true);
+ message.addExtension(repeatedStringExtension , "215");
+ message.addExtension(repeatedBytesExtension , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
+
+ message.addExtension(repeatedStringPieceExtension, "224");
+ message.addExtension(repeatedCordExtension, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32Extension , 301);
+ message.addExtension(repeatedInt64Extension , 302L);
+ message.addExtension(repeatedUint32Extension , 303);
+ message.addExtension(repeatedUint64Extension , 304L);
+ message.addExtension(repeatedSint32Extension , 305);
+ message.addExtension(repeatedSint64Extension , 306L);
+ message.addExtension(repeatedFixed32Extension , 307);
+ message.addExtension(repeatedFixed64Extension , 308L);
+ message.addExtension(repeatedSfixed32Extension, 309);
+ message.addExtension(repeatedSfixed64Extension, 310L);
+ message.addExtension(repeatedFloatExtension , 311F);
+ message.addExtension(repeatedDoubleExtension , 312D);
+ message.addExtension(repeatedBoolExtension , false);
+ message.addExtension(repeatedStringExtension , "315");
+ message.addExtension(repeatedBytesExtension , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.addExtension(repeatedStringPieceExtension, "324");
+ message.addExtension(repeatedCordExtension, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32Extension , 401);
+ message.setExtension(defaultInt64Extension , 402L);
+ message.setExtension(defaultUint32Extension , 403);
+ message.setExtension(defaultUint64Extension , 404L);
+ message.setExtension(defaultSint32Extension , 405);
+ message.setExtension(defaultSint64Extension , 406L);
+ message.setExtension(defaultFixed32Extension , 407);
+ message.setExtension(defaultFixed64Extension , 408L);
+ message.setExtension(defaultSfixed32Extension, 409);
+ message.setExtension(defaultSfixed64Extension, 410L);
+ message.setExtension(defaultFloatExtension , 411F);
+ message.setExtension(defaultDoubleExtension , 412D);
+ message.setExtension(defaultBoolExtension , false);
+ message.setExtension(defaultStringExtension , "415");
+ message.setExtension(defaultBytesExtension , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(defaultStringPieceExtension, "424");
+ message.setExtension(defaultCordExtension, "425");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensions.Builder message) {
+ message.setExtension(repeatedInt32Extension , 1, 501);
+ message.setExtension(repeatedInt64Extension , 1, 502L);
+ message.setExtension(repeatedUint32Extension , 1, 503);
+ message.setExtension(repeatedUint64Extension , 1, 504L);
+ message.setExtension(repeatedSint32Extension , 1, 505);
+ message.setExtension(repeatedSint64Extension , 1, 506L);
+ message.setExtension(repeatedFixed32Extension , 1, 507);
+ message.setExtension(repeatedFixed64Extension , 1, 508L);
+ message.setExtension(repeatedSfixed32Extension, 1, 509);
+ message.setExtension(repeatedSfixed64Extension, 1, 510L);
+ message.setExtension(repeatedFloatExtension , 1, 511F);
+ message.setExtension(repeatedDoubleExtension , 1, 512D);
+ message.setExtension(repeatedBoolExtension , 1, true);
+ message.setExtension(repeatedStringExtension , 1, "515");
+ message.setExtension(repeatedBytesExtension , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtension, 1,
+ RepeatedGroup_extension.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtension, 1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtension, 1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(repeatedStringPieceExtension, 1, "524");
+ message.setExtension(repeatedCordExtension, 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(
+ TestAllExtensionsOrBuilder message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalInt64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtension ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtension ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtension ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(optionalCordExtension));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+ assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtension));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtension));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultInt64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtension ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtension ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(defaultCordExtension));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalInt64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtension ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtension ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtension ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(optionalCordExtension));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("", message.getExtension(optionalCordExtension));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
+
+ // Repeated fields are empty via getExtension().size().
+ Assert.assertEquals(0, message.getExtension(repeatedInt32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedInt64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFloatExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBoolExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedStringExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBytesExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedGroupExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultInt64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtension ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtension ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(defaultCordExtension));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensions.Builder message) {
+ message.addExtension(packedInt32Extension , 601);
+ message.addExtension(packedInt64Extension , 602L);
+ message.addExtension(packedUint32Extension , 603);
+ message.addExtension(packedUint64Extension , 604L);
+ message.addExtension(packedSint32Extension , 605);
+ message.addExtension(packedSint64Extension , 606L);
+ message.addExtension(packedFixed32Extension , 607);
+ message.addExtension(packedFixed64Extension , 608L);
+ message.addExtension(packedSfixed32Extension, 609);
+ message.addExtension(packedSfixed64Extension, 610L);
+ message.addExtension(packedFloatExtension , 611F);
+ message.addExtension(packedDoubleExtension , 612D);
+ message.addExtension(packedBoolExtension , true);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32Extension , 701);
+ message.addExtension(packedInt64Extension , 702L);
+ message.addExtension(packedUint32Extension , 703);
+ message.addExtension(packedUint64Extension , 704L);
+ message.addExtension(packedSint32Extension , 705);
+ message.addExtension(packedSint64Extension , 706L);
+ message.addExtension(packedFixed32Extension , 707);
+ message.addExtension(packedFixed64Extension , 708L);
+ message.addExtension(packedSfixed32Extension, 709);
+ message.addExtension(packedSfixed64Extension, 710L);
+ message.addExtension(packedFloatExtension , 711F);
+ message.addExtension(packedDoubleExtension , 712D);
+ message.addExtension(packedBoolExtension , false);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensions message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
+ assertEqualsExactType(601 , message.getExtension(packedInt32Extension , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64Extension , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32Extension , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64Extension , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32Extension , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64Extension , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32Extension , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32Extension, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtension , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtension , 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(packedEnumExtension, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32Extension , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64Extension , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32Extension , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64Extension , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32Extension , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64Extension , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32Extension , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32Extension, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtension , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtension , 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(packedEnumExtension, 1));
+ }
+
+ // =================================================================
+
+ /**
+ * Performs the same things that the methods of {@code TestUtil} do, but
+ * via the reflection interface. This is its own class because it needs
+ * to know what descriptor to use.
+ */
+ public static class ReflectionTester {
+ private final Descriptors.Descriptor baseDescriptor;
+ private final ExtensionRegistry extensionRegistry;
+
+ private final Descriptors.FileDescriptor file;
+ private final Descriptors.FileDescriptor importFile;
+ private final Descriptors.FileDescriptor publicImportFile;
+
+ private final Descriptors.Descriptor optionalGroup;
+ private final Descriptors.Descriptor repeatedGroup;
+ private final Descriptors.Descriptor nestedMessage;
+ private final Descriptors.Descriptor foreignMessage;
+ private final Descriptors.Descriptor importMessage;
+ private final Descriptors.Descriptor publicImportMessage;
+
+ private final Descriptors.FieldDescriptor groupA;
+ private final Descriptors.FieldDescriptor repeatedGroupA;
+ private final Descriptors.FieldDescriptor nestedB;
+ private final Descriptors.FieldDescriptor foreignC;
+ private final Descriptors.FieldDescriptor importD;
+ private final Descriptors.FieldDescriptor importE;
+
+ private final Descriptors.EnumDescriptor nestedEnum;
+ private final Descriptors.EnumDescriptor foreignEnum;
+ private final Descriptors.EnumDescriptor importEnum;
+
+ private final Descriptors.EnumValueDescriptor nestedFoo;
+ private final Descriptors.EnumValueDescriptor nestedBar;
+ private final Descriptors.EnumValueDescriptor nestedBaz;
+ private final Descriptors.EnumValueDescriptor foreignFoo;
+ private final Descriptors.EnumValueDescriptor foreignBar;
+ private final Descriptors.EnumValueDescriptor foreignBaz;
+ private final Descriptors.EnumValueDescriptor importFoo;
+ private final Descriptors.EnumValueDescriptor importBar;
+ private final Descriptors.EnumValueDescriptor importBaz;
+
+ /**
+ * Construct a {@code ReflectionTester} that will expect messages using
+ * the given descriptor.
+ *
+ * Normally {@code baseDescriptor} should be a descriptor for the type
+ * {@code TestAllTypes}, defined in
+ * {@code google/protobuf/unittest.proto}. However, if
+ * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should
+ * be for {@code TestAllExtensions} instead, and instead of reading and
+ * writing normal fields, the tester will read and write extensions.
+ * All of {@code TestAllExtensions}' extensions must be registered in the
+ * registry.
+ */
+ public ReflectionTester(Descriptors.Descriptor baseDescriptor,
+ ExtensionRegistry extensionRegistry) {
+ this.baseDescriptor = baseDescriptor;
+ this.extensionRegistry = extensionRegistry;
+
+ this.file = baseDescriptor.getFile();
+ Assert.assertEquals(1, file.getDependencies().size());
+ this.importFile = file.getDependencies().get(0);
+ this.publicImportFile = importFile.getDependencies().get(0);
+
+ Descriptors.Descriptor testAllTypes;
+ if (baseDescriptor.getName() == "TestAllTypes") {
+ testAllTypes = baseDescriptor;
+ } else {
+ testAllTypes = file.findMessageTypeByName("TestAllTypes");
+ Assert.assertNotNull(testAllTypes);
+ }
+
+ if (extensionRegistry == null) {
+ // Use testAllTypes, rather than baseDescriptor, to allow
+ // initialization using TestPackedTypes descriptors. These objects
+ // won't be used by the methods for packed fields.
+ this.optionalGroup =
+ testAllTypes.findNestedTypeByName("OptionalGroup");
+ this.repeatedGroup =
+ testAllTypes.findNestedTypeByName("RepeatedGroup");
+ } else {
+ this.optionalGroup =
+ file.findMessageTypeByName("OptionalGroup_extension");
+ this.repeatedGroup =
+ file.findMessageTypeByName("RepeatedGroup_extension");
+ }
+ this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
+ this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
+ this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+ this.publicImportMessage = publicImportFile.findMessageTypeByName(
+ "PublicImportMessage");
+
+ this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
+ this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
+ this.importEnum = importFile.findEnumTypeByName("ImportEnum");
+
+ Assert.assertNotNull(optionalGroup );
+ Assert.assertNotNull(repeatedGroup );
+ Assert.assertNotNull(nestedMessage );
+ Assert.assertNotNull(foreignMessage);
+ Assert.assertNotNull(importMessage );
+ Assert.assertNotNull(nestedEnum );
+ Assert.assertNotNull(foreignEnum );
+ Assert.assertNotNull(importEnum );
+
+ this.nestedB = nestedMessage .findFieldByName("bb");
+ this.foreignC = foreignMessage.findFieldByName("c");
+ this.importD = importMessage .findFieldByName("d");
+ this.importE = publicImportMessage.findFieldByName("e");
+ this.nestedFoo = nestedEnum.findValueByName("FOO");
+ this.nestedBar = nestedEnum.findValueByName("BAR");
+ this.nestedBaz = nestedEnum.findValueByName("BAZ");
+ this.foreignFoo = foreignEnum.findValueByName("FOREIGN_FOO");
+ this.foreignBar = foreignEnum.findValueByName("FOREIGN_BAR");
+ this.foreignBaz = foreignEnum.findValueByName("FOREIGN_BAZ");
+ this.importFoo = importEnum.findValueByName("IMPORT_FOO");
+ this.importBar = importEnum.findValueByName("IMPORT_BAR");
+ this.importBaz = importEnum.findValueByName("IMPORT_BAZ");
+
+ this.groupA = optionalGroup.findFieldByName("a");
+ this.repeatedGroupA = repeatedGroup.findFieldByName("a");
+
+ Assert.assertNotNull(groupA );
+ Assert.assertNotNull(repeatedGroupA);
+ Assert.assertNotNull(nestedB );
+ Assert.assertNotNull(foreignC );
+ Assert.assertNotNull(importD );
+ Assert.assertNotNull(importE );
+ Assert.assertNotNull(nestedFoo );
+ Assert.assertNotNull(nestedBar );
+ Assert.assertNotNull(nestedBaz );
+ Assert.assertNotNull(foreignFoo );
+ Assert.assertNotNull(foreignBar );
+ Assert.assertNotNull(foreignBaz );
+ Assert.assertNotNull(importFoo );
+ Assert.assertNotNull(importBar );
+ Assert.assertNotNull(importBaz );
+ }
+
+ /**
+ * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+ */
+ private Descriptors.FieldDescriptor f(String name) {
+ Descriptors.FieldDescriptor result;
+ if (extensionRegistry == null) {
+ result = baseDescriptor.findFieldByName(name);
+ } else {
+ result = file.findExtensionByName(name + "_extension");
+ }
+ Assert.assertNotNull(result);
+ return result;
+ }
+
+ /**
+ * Calls {@code parent.newBuilderForField()} or uses the
+ * {@code ExtensionRegistry} to find an appropriate builder, depending
+ * on what type is being tested.
+ */
+ private Message.Builder newBuilderForField(
+ Message.Builder parent, Descriptors.FieldDescriptor field) {
+ if (extensionRegistry == null) {
+ return parent.newBuilderForField(field);
+ } else {
+ ExtensionRegistry.ExtensionInfo extension =
+ extensionRegistry.findExtensionByNumber(field.getContainingType(),
+ field.getNumber());
+ Assert.assertNotNull(extension);
+ Assert.assertNotNull(extension.defaultInstance);
+ return extension.defaultInstance.newBuilderForType();
+ }
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}, using the {@link Message.Builder}
+ * reflection interface.
+ */
+ void setAllFieldsViaReflection(Message.Builder message) {
+ message.setField(f("optional_int32" ), 101 );
+ message.setField(f("optional_int64" ), 102L);
+ message.setField(f("optional_uint32" ), 103 );
+ message.setField(f("optional_uint64" ), 104L);
+ message.setField(f("optional_sint32" ), 105 );
+ message.setField(f("optional_sint64" ), 106L);
+ message.setField(f("optional_fixed32" ), 107 );
+ message.setField(f("optional_fixed64" ), 108L);
+ message.setField(f("optional_sfixed32"), 109 );
+ message.setField(f("optional_sfixed64"), 110L);
+ message.setField(f("optional_float" ), 111F);
+ message.setField(f("optional_double" ), 112D);
+ message.setField(f("optional_bool" ), true);
+ message.setField(f("optional_string" ), "115");
+ message.setField(f("optional_bytes" ), toBytes("116"));
+
+ message.setField(f("optionalgroup"),
+ newBuilderForField(message, f("optionalgroup"))
+ .setField(groupA, 117).build());
+ message.setField(f("optional_nested_message"),
+ newBuilderForField(message, f("optional_nested_message"))
+ .setField(nestedB, 118).build());
+ message.setField(f("optional_foreign_message"),
+ newBuilderForField(message, f("optional_foreign_message"))
+ .setField(foreignC, 119).build());
+ message.setField(f("optional_import_message"),
+ newBuilderForField(message, f("optional_import_message"))
+ .setField(importD, 120).build());
+ message.setField(f("optional_public_import_message"),
+ newBuilderForField(message, f("optional_public_import_message"))
+ .setField(importE, 126).build());
+ message.setField(f("optional_lazy_message"),
+ newBuilderForField(message, f("optional_lazy_message"))
+ .setField(nestedB, 127).build());
+
+ message.setField(f("optional_nested_enum" ), nestedBaz);
+ message.setField(f("optional_foreign_enum"), foreignBaz);
+ message.setField(f("optional_import_enum" ), importBaz);
+
+ message.setField(f("optional_string_piece" ), "124");
+ message.setField(f("optional_cord" ), "125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedField(f("repeated_int32" ), 201 );
+ message.addRepeatedField(f("repeated_int64" ), 202L);
+ message.addRepeatedField(f("repeated_uint32" ), 203 );
+ message.addRepeatedField(f("repeated_uint64" ), 204L);
+ message.addRepeatedField(f("repeated_sint32" ), 205 );
+ message.addRepeatedField(f("repeated_sint64" ), 206L);
+ message.addRepeatedField(f("repeated_fixed32" ), 207 );
+ message.addRepeatedField(f("repeated_fixed64" ), 208L);
+ message.addRepeatedField(f("repeated_sfixed32"), 209 );
+ message.addRepeatedField(f("repeated_sfixed64"), 210L);
+ message.addRepeatedField(f("repeated_float" ), 211F);
+ message.addRepeatedField(f("repeated_double" ), 212D);
+ message.addRepeatedField(f("repeated_bool" ), true);
+ message.addRepeatedField(f("repeated_string" ), "215");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("216"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 217).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 218).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 219).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 220).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 227).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBar);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
+ message.addRepeatedField(f("repeated_import_enum" ), importBar);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "224");
+ message.addRepeatedField(f("repeated_cord" ), "225");
+
+ // Add a second one of each field.
+ message.addRepeatedField(f("repeated_int32" ), 301 );
+ message.addRepeatedField(f("repeated_int64" ), 302L);
+ message.addRepeatedField(f("repeated_uint32" ), 303 );
+ message.addRepeatedField(f("repeated_uint64" ), 304L);
+ message.addRepeatedField(f("repeated_sint32" ), 305 );
+ message.addRepeatedField(f("repeated_sint64" ), 306L);
+ message.addRepeatedField(f("repeated_fixed32" ), 307 );
+ message.addRepeatedField(f("repeated_fixed64" ), 308L);
+ message.addRepeatedField(f("repeated_sfixed32"), 309 );
+ message.addRepeatedField(f("repeated_sfixed64"), 310L);
+ message.addRepeatedField(f("repeated_float" ), 311F);
+ message.addRepeatedField(f("repeated_double" ), 312D);
+ message.addRepeatedField(f("repeated_bool" ), false);
+ message.addRepeatedField(f("repeated_string" ), "315");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("316"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 317).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 318).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 319).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 320).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 327).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
+ message.addRepeatedField(f("repeated_import_enum" ), importBaz);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "324");
+ message.addRepeatedField(f("repeated_cord" ), "325");
+
+ // -----------------------------------------------------------------
+
+ message.setField(f("default_int32" ), 401 );
+ message.setField(f("default_int64" ), 402L);
+ message.setField(f("default_uint32" ), 403 );
+ message.setField(f("default_uint64" ), 404L);
+ message.setField(f("default_sint32" ), 405 );
+ message.setField(f("default_sint64" ), 406L);
+ message.setField(f("default_fixed32" ), 407 );
+ message.setField(f("default_fixed64" ), 408L);
+ message.setField(f("default_sfixed32"), 409 );
+ message.setField(f("default_sfixed64"), 410L);
+ message.setField(f("default_float" ), 411F);
+ message.setField(f("default_double" ), 412D);
+ message.setField(f("default_bool" ), false);
+ message.setField(f("default_string" ), "415");
+ message.setField(f("default_bytes" ), toBytes("416"));
+
+ message.setField(f("default_nested_enum" ), nestedFoo);
+ message.setField(f("default_foreign_enum"), foreignFoo);
+ message.setField(f("default_import_enum" ), importFoo);
+
+ message.setField(f("default_string_piece" ), "424");
+ message.setField(f("default_cord" ), "425");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}, using the
+ * {@link Message.Builder} reflection interface.
+ */
+ void modifyRepeatedFieldsViaReflection(Message.Builder message) {
+ message.setRepeatedField(f("repeated_int32" ), 1, 501 );
+ message.setRepeatedField(f("repeated_int64" ), 1, 502L);
+ message.setRepeatedField(f("repeated_uint32" ), 1, 503 );
+ message.setRepeatedField(f("repeated_uint64" ), 1, 504L);
+ message.setRepeatedField(f("repeated_sint32" ), 1, 505 );
+ message.setRepeatedField(f("repeated_sint64" ), 1, 506L);
+ message.setRepeatedField(f("repeated_fixed32" ), 1, 507 );
+ message.setRepeatedField(f("repeated_fixed64" ), 1, 508L);
+ message.setRepeatedField(f("repeated_sfixed32"), 1, 509 );
+ message.setRepeatedField(f("repeated_sfixed64"), 1, 510L);
+ message.setRepeatedField(f("repeated_float" ), 1, 511F);
+ message.setRepeatedField(f("repeated_double" ), 1, 512D);
+ message.setRepeatedField(f("repeated_bool" ), 1, true);
+ message.setRepeatedField(f("repeated_string" ), 1, "515");
+ message.setRepeatedField(f("repeated_bytes" ), 1, toBytes("516"));
+
+ message.setRepeatedField(f("repeatedgroup"), 1,
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 517).build());
+ message.setRepeatedField(f("repeated_nested_message"), 1,
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 518).build());
+ message.setRepeatedField(f("repeated_foreign_message"), 1,
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 519).build());
+ message.setRepeatedField(f("repeated_import_message"), 1,
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 520).build());
+ message.setRepeatedField(f("repeated_lazy_message"), 1,
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 527).build());
+
+ message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo);
+ message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
+ message.setRepeatedField(f("repeated_import_enum" ), 1, importFoo);
+
+ message.setRepeatedField(f("repeated_string_piece"), 1, "524");
+ message.setRepeatedField(f("repeated_cord"), 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields},
+ * using the {@link Message} reflection interface.
+ */
+ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertTrue(message.hasField(f("optional_int32" )));
+ Assert.assertTrue(message.hasField(f("optional_int64" )));
+ Assert.assertTrue(message.hasField(f("optional_uint32" )));
+ Assert.assertTrue(message.hasField(f("optional_uint64" )));
+ Assert.assertTrue(message.hasField(f("optional_sint32" )));
+ Assert.assertTrue(message.hasField(f("optional_sint64" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed32" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed64" )));
+ Assert.assertTrue(message.hasField(f("optional_sfixed32")));
+ Assert.assertTrue(message.hasField(f("optional_sfixed64")));
+ Assert.assertTrue(message.hasField(f("optional_float" )));
+ Assert.assertTrue(message.hasField(f("optional_double" )));
+ Assert.assertTrue(message.hasField(f("optional_bool" )));
+ Assert.assertTrue(message.hasField(f("optional_string" )));
+ Assert.assertTrue(message.hasField(f("optional_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("optionalgroup" )));
+ Assert.assertTrue(message.hasField(f("optional_nested_message" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_message")));
+ Assert.assertTrue(message.hasField(f("optional_import_message" )));
+
+ Assert.assertTrue(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+
+ Assert.assertTrue(message.hasField(f("optional_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("optional_string_piece")));
+ Assert.assertTrue(message.hasField(f("optional_cord")));
+
+ Assert.assertEquals(101 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(102L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(103 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(104L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(105 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(106L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(107 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(108L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(109 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(110L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(111F , message.getField(f("optional_float" )));
+ Assert.assertEquals(112D , message.getField(f("optional_double" )));
+ Assert.assertEquals(true , message.getField(f("optional_bool" )));
+ Assert.assertEquals("115", message.getField(f("optional_string" )));
+ Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes")));
+
+ Assert.assertEquals(117,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(118,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(119,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(120,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(126,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(127,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("124", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("125", message.getField(f("optional_cord")));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(301 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(303 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(305 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(307 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(309 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("315", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(317,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(318,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(319,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(320,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(327,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasField(f("default_int32" )));
+ Assert.assertTrue(message.hasField(f("default_int64" )));
+ Assert.assertTrue(message.hasField(f("default_uint32" )));
+ Assert.assertTrue(message.hasField(f("default_uint64" )));
+ Assert.assertTrue(message.hasField(f("default_sint32" )));
+ Assert.assertTrue(message.hasField(f("default_sint64" )));
+ Assert.assertTrue(message.hasField(f("default_fixed32" )));
+ Assert.assertTrue(message.hasField(f("default_fixed64" )));
+ Assert.assertTrue(message.hasField(f("default_sfixed32")));
+ Assert.assertTrue(message.hasField(f("default_sfixed64")));
+ Assert.assertTrue(message.hasField(f("default_float" )));
+ Assert.assertTrue(message.hasField(f("default_double" )));
+ Assert.assertTrue(message.hasField(f("default_bool" )));
+ Assert.assertTrue(message.hasField(f("default_string" )));
+ Assert.assertTrue(message.hasField(f("default_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("default_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("default_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("default_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("default_string_piece")));
+ Assert.assertTrue(message.hasField(f("default_cord")));
+
+ Assert.assertEquals(401 , message.getField(f("default_int32" )));
+ Assert.assertEquals(402L , message.getField(f("default_int64" )));
+ Assert.assertEquals(403 , message.getField(f("default_uint32" )));
+ Assert.assertEquals(404L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(405 , message.getField(f("default_sint32" )));
+ Assert.assertEquals(406L , message.getField(f("default_sint64" )));
+ Assert.assertEquals(407 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals(408L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals(409 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(410L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals(411F , message.getField(f("default_float" )));
+ Assert.assertEquals(412D , message.getField(f("default_double" )));
+ Assert.assertEquals(false, message.getField(f("default_bool" )));
+ Assert.assertEquals("415", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("424", message.getField(f("default_string_piece")));
+ Assert.assertEquals("425", message.getField(f("default_cord")));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values, using the {@link Message} reflection interface.
+ */
+ public void assertClearViaReflection(MessageOrBuilder message) {
+ // has_blah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasField(f("optional_int32" )));
+ Assert.assertFalse(message.hasField(f("optional_int64" )));
+ Assert.assertFalse(message.hasField(f("optional_uint32" )));
+ Assert.assertFalse(message.hasField(f("optional_uint64" )));
+ Assert.assertFalse(message.hasField(f("optional_sint32" )));
+ Assert.assertFalse(message.hasField(f("optional_sint64" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed32" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed64" )));
+ Assert.assertFalse(message.hasField(f("optional_sfixed32")));
+ Assert.assertFalse(message.hasField(f("optional_sfixed64")));
+ Assert.assertFalse(message.hasField(f("optional_float" )));
+ Assert.assertFalse(message.hasField(f("optional_double" )));
+ Assert.assertFalse(message.hasField(f("optional_bool" )));
+ Assert.assertFalse(message.hasField(f("optional_string" )));
+ Assert.assertFalse(message.hasField(f("optional_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("optionalgroup" )));
+ Assert.assertFalse(message.hasField(f("optional_nested_message" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_message")));
+ Assert.assertFalse(message.hasField(f("optional_import_message" )));
+
+ Assert.assertFalse(message.hasField(f("optional_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("optional_string_piece")));
+ Assert.assertFalse(message.hasField(f("optional_cord")));
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(0L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(0F , message.getField(f("optional_float" )));
+ Assert.assertEquals(0D , message.getField(f("optional_double" )));
+ Assert.assertEquals(false, message.getField(f("optional_bool" )));
+ Assert.assertEquals("" , message.getField(f("optional_string" )));
+ Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes")));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_public_import_message")))
+ .hasField(importE));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_lazy_message")))
+ .hasField(nestedB));
+
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("", message.getField(f("optional_cord")));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ // has_blah() should also be false for all default fields.
+ Assert.assertFalse(message.hasField(f("default_int32" )));
+ Assert.assertFalse(message.hasField(f("default_int64" )));
+ Assert.assertFalse(message.hasField(f("default_uint32" )));
+ Assert.assertFalse(message.hasField(f("default_uint64" )));
+ Assert.assertFalse(message.hasField(f("default_sint32" )));
+ Assert.assertFalse(message.hasField(f("default_sint64" )));
+ Assert.assertFalse(message.hasField(f("default_fixed32" )));
+ Assert.assertFalse(message.hasField(f("default_fixed64" )));
+ Assert.assertFalse(message.hasField(f("default_sfixed32")));
+ Assert.assertFalse(message.hasField(f("default_sfixed64")));
+ Assert.assertFalse(message.hasField(f("default_float" )));
+ Assert.assertFalse(message.hasField(f("default_double" )));
+ Assert.assertFalse(message.hasField(f("default_bool" )));
+ Assert.assertFalse(message.hasField(f("default_string" )));
+ Assert.assertFalse(message.hasField(f("default_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("default_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("default_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("default_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("default_string_piece" )));
+ Assert.assertFalse(message.hasField(f("default_cord" )));
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getField(f("default_int32" )));
+ Assert.assertEquals( 42L , message.getField(f("default_int64" )));
+ Assert.assertEquals( 43 , message.getField(f("default_uint32" )));
+ Assert.assertEquals( 44L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(-45 , message.getField(f("default_sint32" )));
+ Assert.assertEquals( 46L , message.getField(f("default_sint64" )));
+ Assert.assertEquals( 47 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals( 48L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals( 49 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(-50L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals( 51.5F , message.getField(f("default_float" )));
+ Assert.assertEquals( 52e3D , message.getField(f("default_double" )));
+ Assert.assertEquals(true , message.getField(f("default_bool" )));
+ Assert.assertEquals("hello", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importBar, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("abc", message.getField(f("default_string_piece")));
+ Assert.assertEquals("123", message.getField(f("default_cord")));
+ }
+
+
+ // ---------------------------------------------------------------
+
+ public void assertRepeatedFieldsModifiedViaReflection(
+ MessageOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(501 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(503 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(505 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(507 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(509 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("515", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(517,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(518,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(519,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(520,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(527,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
+ }
+
+ public void setPackedFieldsViaReflection(Message.Builder message) {
+ message.addRepeatedField(f("packed_int32" ), 601 );
+ message.addRepeatedField(f("packed_int64" ), 602L);
+ message.addRepeatedField(f("packed_uint32" ), 603 );
+ message.addRepeatedField(f("packed_uint64" ), 604L);
+ message.addRepeatedField(f("packed_sint32" ), 605 );
+ message.addRepeatedField(f("packed_sint64" ), 606L);
+ message.addRepeatedField(f("packed_fixed32" ), 607 );
+ message.addRepeatedField(f("packed_fixed64" ), 608L);
+ message.addRepeatedField(f("packed_sfixed32"), 609 );
+ message.addRepeatedField(f("packed_sfixed64"), 610L);
+ message.addRepeatedField(f("packed_float" ), 611F);
+ message.addRepeatedField(f("packed_double" ), 612D);
+ message.addRepeatedField(f("packed_bool" ), true);
+ message.addRepeatedField(f("packed_enum" ), foreignBar);
+ // Add a second one of each field.
+ message.addRepeatedField(f("packed_int32" ), 701 );
+ message.addRepeatedField(f("packed_int64" ), 702L);
+ message.addRepeatedField(f("packed_uint32" ), 703 );
+ message.addRepeatedField(f("packed_uint64" ), 704L);
+ message.addRepeatedField(f("packed_sint32" ), 705 );
+ message.addRepeatedField(f("packed_sint64" ), 706L);
+ message.addRepeatedField(f("packed_fixed32" ), 707 );
+ message.addRepeatedField(f("packed_fixed64" ), 708L);
+ message.addRepeatedField(f("packed_sfixed32"), 709 );
+ message.addRepeatedField(f("packed_sfixed64"), 710L);
+ message.addRepeatedField(f("packed_float" ), 711F);
+ message.addRepeatedField(f("packed_double" ), 712D);
+ message.addRepeatedField(f("packed_bool" ), false);
+ message.addRepeatedField(f("packed_enum" ), foreignBaz);
+ }
+
+ public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum" )));
+ Assert.assertEquals(601 , message.getRepeatedField(f("packed_int32" ), 0));
+ Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64" ), 0));
+ Assert.assertEquals(603 , message.getRepeatedField(f("packed_uint32" ), 0));
+ Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64" ), 0));
+ Assert.assertEquals(605 , message.getRepeatedField(f("packed_sint32" ), 0));
+ Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64" ), 0));
+ Assert.assertEquals(607 , message.getRepeatedField(f("packed_fixed32" ), 0));
+ Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
+ Assert.assertEquals(609 , message.getRepeatedField(f("packed_sfixed32"), 0));
+ Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
+ Assert.assertEquals(611F , message.getRepeatedField(f("packed_float" ), 0));
+ Assert.assertEquals(612D , message.getRepeatedField(f("packed_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("packed_bool" ), 0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
+ Assert.assertEquals(701 , message.getRepeatedField(f("packed_int32" ), 1));
+ Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64" ), 1));
+ Assert.assertEquals(703 , message.getRepeatedField(f("packed_uint32" ), 1));
+ Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64" ), 1));
+ Assert.assertEquals(705 , message.getRepeatedField(f("packed_sint32" ), 1));
+ Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64" ), 1));
+ Assert.assertEquals(707 , message.getRepeatedField(f("packed_fixed32" ), 1));
+ Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
+ Assert.assertEquals(709 , message.getRepeatedField(f("packed_sfixed32"), 1));
+ Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
+ Assert.assertEquals(711F , message.getRepeatedField(f("packed_float" ), 1));
+ Assert.assertEquals(712D , message.getRepeatedField(f("packed_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("packed_bool" ), 1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
+ }
+
+ /**
+ * Verifies that the reflection setters for the given.Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an
+ * appropriate assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ try {
+ builder.setField(f("optional_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage.Builder) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addRepeatedField(f("repeated_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_message"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ /**
+ * Verifies that the reflection repeated setters for the given Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate
+ * assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ builder.addRepeatedField(f("repeated_string"), "one");
+ try {
+ builder.setRepeatedField(f("repeated_string"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
+ try {
+ builder.setRepeatedField(f("repeated_bytes"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
+ try {
+ builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(
+ f("repeated_nested_message"),
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ try {
+ builder.setRepeatedField(f("repeated_nested_message"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+ }
+
+ /**
+ * @param filePath The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static String readTextFromFile(String filePath) {
+ return readBytesFromFile(filePath).toStringUtf8();
+ }
+
+ private static File getTestDataDir() {
+ // Search each parent directory looking for "src/google/protobuf".
+ File ancestor = new File(".");
+ try {
+ ancestor = ancestor.getCanonicalFile();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Couldn't get canonical name of working directory.", e);
+ }
+ while (ancestor != null && ancestor.exists()) {
+ if (new File(ancestor, "src/google/protobuf").exists()) {
+ return new File(ancestor, "src/google/protobuf/testdata");
+ }
+ ancestor = ancestor.getParentFile();
+ }
+
+ throw new RuntimeException(
+ "Could not find golden files. This test must be run from within the " +
+ "protobuf source package so that it can read test data files from the " +
+ "C++ source tree: " + new File(".").getAbsolutePath());
+ }
+
+ /**
+ * @param filename The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static ByteString readBytesFromFile(String filename) {
+ File fullPath = new File(getTestDataDir(), filename);
+ try {
+ RandomAccessFile file = new RandomAccessFile(fullPath, "r");
+ byte[] content = new byte[(int) file.length()];
+ file.readFully(content);
+ return ByteString.copyFrom(content);
+ } catch (IOException e) {
+ // Throw a RuntimeException here so that we can call this function from
+ // static initializers.
+ throw new IllegalArgumentException(
+ "Couldn't read file: " + fullPath.getPath(), e);
+ }
+ }
+
+ /**
+ * Get the bytes of the "golden message". This is a serialized TestAllTypes
+ * with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
+ * on disk rather than generated dynamically. The file is actually generated
+ * by C++ code, so testing against it verifies compatibility with C++.
+ */
+ public static ByteString getGoldenMessage() {
+ if (goldenMessage == null) {
+ goldenMessage = readBytesFromFile("golden_message");
+ }
+ return goldenMessage;
+ }
+ private static ByteString goldenMessage = null;
+
+ /**
+ * Get the bytes of the "golden packed fields message". This is a serialized
+ * TestPackedTypes with all fields set as they would be by
+ * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+ * file on disk rather than generated dynamically. The file is actually
+ * generated by C++ code, so testing against it verifies compatibility with
+ * C++.
+ */
+ public static ByteString getGoldenPackedFieldsMessage() {
+ if (goldenPackedFieldsMessage == null) {
+ goldenPackedFieldsMessage =
+ readBytesFromFile("golden_packed_fields_message");
+ }
+ return goldenPackedFieldsMessage;
+ }
+ private static ByteString goldenPackedFieldsMessage = null;
+
+ public static abstract class HackMessage extends GeneratedMessage {
+ public interface MyInterface extends BuilderParent {
+ }
+ }
+ /**
+ * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+ public static class MockBuilderParent
+ implements HackMessage.MyInterface {
+
+ private int invalidations;
+
+ //@Override (Java 1.6 override semantics, but we must support 1.5)
+ public void markDirty() {
+ invalidations++;
+ }
+
+ public int getInvalidationCount() {
+ return invalidations;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java
new file mode 100644
index 0000000000..edcc8908a4
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/TextFormatTest.java
@@ -0,0 +1,536 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestMset.TestMessageSet;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto.OneString;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+
+import junit.framework.TestCase;
+
+import java.io.StringReader;
+
+/**
+ * Test case for {@link TextFormat}.
+ *
+ * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
+ *
+ * @author wenboz@google.com (Wenbo Zhu)
+ */
+public class TextFormatTest extends TestCase {
+
+ // A basic string with different escapable characters for testing.
+ private final static String kEscapeTestString =
+ "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+ + "slashes \\";
+
+ // A representation of the above string with all the characters escaped.
+ private final static String kEscapeTestStringEscaped =
+ "\\\"A string with \\' characters \\n and \\r newlines "
+ + "and \\t tabs and \\001 slashes \\\\";
+
+ private static String allFieldsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_data.txt");
+ private static String allExtensionsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_extensions_data.txt");
+
+ private static String exoticText =
+ "repeated_int32: -1\n" +
+ "repeated_int32: -2147483648\n" +
+ "repeated_int64: -1\n" +
+ "repeated_int64: -9223372036854775808\n" +
+ "repeated_uint32: 4294967295\n" +
+ "repeated_uint32: 2147483648\n" +
+ "repeated_uint64: 18446744073709551615\n" +
+ "repeated_uint64: 9223372036854775808\n" +
+ "repeated_double: 123.0\n" +
+ "repeated_double: 123.5\n" +
+ "repeated_double: 0.125\n" +
+ "repeated_double: .125\n" +
+ "repeated_double: -.125\n" +
+ "repeated_double: 1.23E17\n" +
+ "repeated_double: 1.23E+17\n" +
+ "repeated_double: -1.23e-17\n" +
+ "repeated_double: .23e+17\n" +
+ "repeated_double: -.23E17\n" +
+ "repeated_double: 1.235E22\n" +
+ "repeated_double: 1.235E-18\n" +
+ "repeated_double: 123.456789\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n" +
+ "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
+ "\\341\\210\\264\"\n" +
+ "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+
+ private static String canonicalExoticText =
+ exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16");
+
+ private String messageSetText =
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 123\n" +
+ "}\n" +
+ "[protobuf_unittest.TestMessageSetExtension2] {\n" +
+ " str: \"foo\"\n" +
+ "}\n";
+
+ /** Print TestAllTypes and compare with golden file. */
+ public void testPrintMessage() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllTypes as Builder and compare with golden file. */
+ public void testPrintMessageBuilder() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllExtensions and compare with golden file. */
+ public void testPrintExtensions() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allExtensionsSetText, javaText);
+ }
+
+ // Creates an example unknown field set.
+ private UnknownFieldSet makeUnknownFieldSet() {
+ return UnknownFieldSet.newBuilder()
+ .addField(5,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addFixed32(2)
+ .addFixed64(3)
+ .addLengthDelimited(ByteString.copyFromUtf8("4"))
+ .addGroup(
+ UnknownFieldSet.newBuilder()
+ .addField(10,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(5)
+ .build())
+ .build())
+ .build())
+ .addField(8,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addVarint(2)
+ .addVarint(3)
+ .build())
+ .addField(15,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0xABCDEF1234567890L)
+ .addFixed32(0xABCD1234)
+ .addFixed64(0xABCDEF1234567890L)
+ .build())
+ .build();
+ }
+
+ public void testPrintUnknownFields() throws Exception {
+ // Test printing of unknown fields in a message.
+
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(makeUnknownFieldSet())
+ .build();
+
+ assertEquals(
+ "5: 1\n" +
+ "5: 0x00000002\n" +
+ "5: 0x0000000000000003\n" +
+ "5: \"4\"\n" +
+ "5 {\n" +
+ " 10: 5\n" +
+ "}\n" +
+ "8: 1\n" +
+ "8: 2\n" +
+ "8: 3\n" +
+ "15: 12379813812177893520\n" +
+ "15: 0xabcd1234\n" +
+ "15: 0xabcdef1234567890\n",
+ TextFormat.printToString(message));
+ }
+
+ public void testPrintField() throws Exception {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"\n",
+ TextFormat.printFieldToString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message {\n bb: 42\n}\n",
+ TextFormat.printFieldToString(optionalField, value));
+ }
+
+ /**
+ * Helper to construct a ByteString from a String containing only 8-bit
+ * characters. The characters are converted directly to bytes, *not*
+ * encoded using UTF-8.
+ */
+ private ByteString bytes(String str) throws Exception {
+ return ByteString.copyFrom(str.getBytes("ISO-8859-1"));
+ }
+
+ /**
+ * Helper to construct a ByteString from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private ByteString bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return ByteString.copyFrom(bytes);
+ }
+
+ public void testPrintExotic() throws Exception {
+ Message message = TestAllTypes.newBuilder()
+ // Signed vs. unsigned numbers.
+ .addRepeatedInt32 (-1)
+ .addRepeatedUint32(-1)
+ .addRepeatedInt64 (-1)
+ .addRepeatedUint64(-1)
+
+ .addRepeatedInt32 (1 << 31)
+ .addRepeatedUint32(1 << 31)
+ .addRepeatedInt64 (1l << 63)
+ .addRepeatedUint64(1l << 63)
+
+ // Floats of various precisions and exponents.
+ .addRepeatedDouble(123)
+ .addRepeatedDouble(123.5)
+ .addRepeatedDouble(0.125)
+ .addRepeatedDouble(.125)
+ .addRepeatedDouble(-.125)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(-1.23e-17)
+ .addRepeatedDouble(.23e17)
+ .addRepeatedDouble(-23e15)
+ .addRepeatedDouble(123.5e20)
+ .addRepeatedDouble(123.5e-20)
+ .addRepeatedDouble(123.456789)
+ .addRepeatedDouble(Double.POSITIVE_INFINITY)
+ .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+ .addRepeatedDouble(Double.NaN)
+
+ // Strings and bytes that needing escaping.
+ .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
+ .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
+ .build();
+
+ assertEquals(canonicalExoticText, message.toString());
+ }
+
+ public void testPrintMessageSet() throws Exception {
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .build();
+
+ assertEquals(messageSetText, messageSet.toString());
+ }
+
+ // =================================================================
+
+ public void testParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(allFieldsSetText, builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseReader() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(new StringReader(allFieldsSetText), builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseExtensions() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TextFormat.merge(allExtensionsSetText,
+ TestUtil.getExtensionRegistry(),
+ builder);
+ TestUtil.assertAllExtensionsSet(builder.build());
+ }
+
+ public void testParseCompatibility() throws Exception {
+ String original = "repeated_float: inf\n" +
+ "repeated_float: -inf\n" +
+ "repeated_float: nan\n" +
+ "repeated_float: inff\n" +
+ "repeated_float: -inff\n" +
+ "repeated_float: nanf\n" +
+ "repeated_float: 1.0f\n" +
+ "repeated_float: infinityf\n" +
+ "repeated_float: -Infinityf\n" +
+ "repeated_double: infinity\n" +
+ "repeated_double: -infinity\n" +
+ "repeated_double: nan\n";
+ String canonical = "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: 1.0\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(original, builder);
+ assertEquals(canonical, builder.build().toString());
+ }
+
+ public void testParseExotic() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(exoticText, builder);
+
+ // Too lazy to check things individually. Don't try to debug this
+ // if testPrintExotic() is failing.
+ assertEquals(canonicalExoticText, builder.build().toString());
+ }
+
+ public void testParseMessageSet() throws Exception {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+ TextFormat.merge(messageSetText, extensionRegistry, builder);
+ TestMessageSet messageSet = builder.build();
+
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension1.messageSetExtension));
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension2.messageSetExtension));
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+ }
+
+ public void testParseNumericEnum() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_nested_enum: 2", builder);
+ assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
+ }
+
+ public void testParseAngleBrackets() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("OptionalGroup: < a: 1 >", builder);
+ assertTrue(builder.hasOptionalGroup());
+ assertEquals(1, builder.getOptionalGroup().getA());
+ }
+
+ public void testParseComment() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(
+ "# this is a comment\n" +
+ "optional_int32: 1 # another comment\n" +
+ "optional_int64: 2\n" +
+ "# EOF comment", builder);
+ assertEquals(1, builder.getOptionalInt32());
+ assertEquals(2, builder.getOptionalInt64());
+ }
+
+ // =================================================================
+
+ public void testParseString() throws Exception {
+ final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + zh + "\"", builder);
+ assertEquals(zh, builder.getOptionalString());
+ }
+
+ public void testParseLongString() throws Exception {
+ String longText =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + longText + "\"", builder);
+ assertEquals(longText, builder.getOptionalString());
+ }
+
+ public void testParseBoolean() throws Exception {
+ String goodText =
+ "repeated_bool: t repeated_bool : 0\n" +
+ "repeated_bool :f repeated_bool:1";
+ String goodTextCanonical =
+ "repeated_bool: true\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: true\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(goodText, builder);
+ assertEquals(goodTextCanonical, builder.build().toString());
+
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool:2", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool: foo", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ }
+
+ public void testParseAdjacentStringLiterals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
+ assertEquals("foocorgegrault", builder.getOptionalString());
+ }
+
+ public void testPrintFieldValue() throws Exception {
+ assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
+ assertPrintFieldValue("123.0", 123f, "repeated_float");
+ assertPrintFieldValue("123.0", 123d, "repeated_double");
+ assertPrintFieldValue("123", 123, "repeated_int32");
+ assertPrintFieldValue("123", 123L, "repeated_int64");
+ assertPrintFieldValue("true", true, "repeated_bool");
+ assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
+ assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL,
+ "repeated_uint64");
+ assertPrintFieldValue("\"\\001\\002\\003\"",
+ ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
+ }
+
+ private void assertPrintFieldValue(String expect, Object value,
+ String fieldName) throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ StringBuilder sb = new StringBuilder();
+ TextFormat.printFieldValue(
+ TestAllTypes.getDescriptor().findFieldByName(fieldName),
+ value, sb);
+ assertEquals(expect, sb.toString());
+ }
+
+ public void testShortDebugString() {
+ assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
+ + " repeated_uint32: 2",
+ TextFormat.shortDebugString(TestAllTypes.newBuilder()
+ .addRepeatedInt32(1)
+ .addRepeatedUint32(2)
+ .setOptionalNestedMessage(
+ NestedMessage.newBuilder().setBb(42).build())
+ .build()));
+ }
+
+ public void testShortDebugString_unknown() {
+ assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+ + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+ + " 0xabcdef1234567890",
+ TextFormat.shortDebugString(makeUnknownFieldSet()));
+ }
+
+ public void testPrintToUnicodeString() {
+ assertEquals(
+ "optional_string: \"abc\u3042efg\"\n" +
+ "optional_bytes: \"\\343\\201\\202\"\n" +
+ "repeated_string: \"\u3093XYZ\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("abc\u3042efg")
+ .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+ .addRepeatedString("\u3093XYZ")
+ .build()));
+ }
+
+ public void testPrintToUnicodeString_unknown() {
+ assertEquals(
+ "1: \"\\343\\201\\202\"\n",
+ TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+ .build()));
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java
new file mode 100644
index 0000000000..b9bfb691b1
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnknownFieldSetTest.java
@@ -0,0 +1,438 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ * Tests related to unknown field handling.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class UnknownFieldSetTest extends TestCase {
+ public void setUp() throws Exception {
+ descriptor = TestAllTypes.getDescriptor();
+ allFields = TestUtil.getAllSet();
+ allFieldsData = allFields.toByteString();
+ emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
+ unknownFields = emptyMessage.getUnknownFields();
+ }
+
+ UnknownFieldSet.Field getField(String name) {
+ Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
+ assertNotNull(field);
+ return unknownFields.getField(field.getNumber());
+ }
+
+ // Constructs a protocol buffer which contains fields with all the same
+ // numbers as allFieldsData except that each field is some other wire
+ // type.
+ ByteString getBizarroData() throws Exception {
+ UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();
+
+ UnknownFieldSet.Field varintField =
+ UnknownFieldSet.Field.newBuilder().addVarint(1).build();
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder().addFixed32(1).build();
+
+ for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+ unknownFields.asMap().entrySet()) {
+ if (entry.getValue().getVarintList().isEmpty()) {
+ // Original field is not a varint, so use a varint.
+ bizarroFields.addField(entry.getKey(), varintField);
+ } else {
+ // Original field *is* a varint, so use something else.
+ bizarroFields.addField(entry.getKey(), fixed32Field);
+ }
+ }
+
+ return bizarroFields.build().toByteString();
+ }
+
+ Descriptors.Descriptor descriptor;
+ TestAllTypes allFields;
+ ByteString allFieldsData;
+
+ // An empty message that has been parsed from allFieldsData. So, it has
+ // unknown fields of every type.
+ TestEmptyMessage emptyMessage;
+ UnknownFieldSet unknownFields;
+
+ // =================================================================
+
+ public void testVarint() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_int32");
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(allFields.getOptionalInt32(),
+ (long) field.getVarintList().get(0));
+ }
+
+ public void testFixed32() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed32");
+ assertEquals(1, field.getFixed32List().size());
+ assertEquals(allFields.getOptionalFixed32(),
+ (int) field.getFixed32List().get(0));
+ }
+
+ public void testFixed64() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed64");
+ assertEquals(1, field.getFixed64List().size());
+ assertEquals(allFields.getOptionalFixed64(),
+ (long) field.getFixed64List().get(0));
+ }
+
+ public void testLengthDelimited() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_bytes");
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals(allFields.getOptionalBytes(),
+ field.getLengthDelimitedList().get(0));
+ }
+
+ public void testGroup() throws Exception {
+ Descriptors.FieldDescriptor nestedFieldDescriptor =
+ TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
+ assertNotNull(nestedFieldDescriptor);
+
+ UnknownFieldSet.Field field = getField("optionalgroup");
+ assertEquals(1, field.getGroupList().size());
+
+ UnknownFieldSet group = field.getGroupList().get(0);
+ assertEquals(1, group.asMap().size());
+ assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));
+
+ UnknownFieldSet.Field nestedField =
+ group.getField(nestedFieldDescriptor.getNumber());
+ assertEquals(1, nestedField.getVarintList().size());
+ assertEquals(allFields.getOptionalGroup().getA(),
+ (long) nestedField.getVarintList().get(0));
+ }
+
+ public void testSerialize() throws Exception {
+ // Check that serializing the UnknownFieldSet produces the original data
+ // again.
+ ByteString data = emptyMessage.toByteString();
+ assertEquals(allFieldsData, data);
+ }
+
+ public void testCopyFrom() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();
+
+ assertEquals(emptyMessage.toString(), message.toString());
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestEmptyMessage source =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(2,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(2).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(4).build())
+ .build())
+ .build();
+ TestEmptyMessage destination =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(3).build())
+ .build())
+ .mergeFrom(source)
+ .build();
+
+ assertEquals(
+ "1: 1\n" +
+ "2: 2\n" +
+ "3: 3\n" +
+ "3: 4\n",
+ destination.toString());
+ }
+
+ public void testClear() throws Exception {
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
+ assertTrue(fields.asMap().isEmpty());
+ }
+
+ public void testClearMessage() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
+ assertEquals(0, message.getSerializedSize());
+ }
+
+ public void testParseKnownAndUnknown() throws Exception {
+ // Test mixing known and unknown fields when parsing.
+
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder(unknownFields)
+ .addField(123456,
+ UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
+ .build();
+
+ ByteString data = fields.toByteString();
+ TestAllTypes destination = TestAllTypes.parseFrom(data);
+
+ TestUtil.assertAllFieldsSet(destination);
+ assertEquals(1, destination.getUnknownFields().asMap().size());
+
+ UnknownFieldSet.Field field =
+ destination.getUnknownFields().getField(123456);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(654321, (long) field.getVarintList().get(0));
+ }
+
+ public void testWrongTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(), allTypesMessage.toString());
+ }
+
+ public void testUnknownExtensions() throws Exception {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ TestEmptyMessageWithExtensions message =
+ TestEmptyMessageWithExtensions.parseFrom(allFieldsData);
+
+ assertEquals(unknownFields.asMap().size(),
+ message.getUnknownFields().asMap().size());
+ assertEquals(allFieldsData, message.toByteString());
+ }
+
+ public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllExtensions allExtensionsMessage =
+ TestAllExtensions.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(),
+ allExtensionsMessage.toString());
+ }
+
+ public void testParseUnknownEnumValue() throws Exception {
+ Descriptors.FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ Descriptors.FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ assertNotNull(singularField);
+ assertNotNull(repeatedField);
+
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(5) // not valid
+ .build())
+ .addField(repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(4) // not valid
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(6) // not valid
+ .build())
+ .build()
+ .toByteString();
+
+ {
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getOptionalNestedEnum());
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getRepeatedNestedEnumList());
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+
+ {
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+ }
+
+ public void testLargeVarint() throws Exception {
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0x7FFFFFFFFFFFFFFFL)
+ .build())
+ .build()
+ .toByteString();
+ UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
+ UnknownFieldSet.Field field = parsed.getField(1);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed32(1)
+ .build();
+ UnknownFieldSet.Field fixed64Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed64(1)
+ .build();
+ UnknownFieldSet.Field varIntField =
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .build();
+ UnknownFieldSet.Field lengthDelimitedField =
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.EMPTY)
+ .build();
+ UnknownFieldSet.Field groupField =
+ UnknownFieldSet.Field.newBuilder()
+ .addGroup(unknownFields)
+ .build();
+
+ UnknownFieldSet a =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed32Field)
+ .build();
+ UnknownFieldSet b =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed64Field)
+ .build();
+ UnknownFieldSet c =
+ UnknownFieldSet.newBuilder()
+ .addField(1, varIntField)
+ .build();
+ UnknownFieldSet d =
+ UnknownFieldSet.newBuilder()
+ .addField(1, lengthDelimitedField)
+ .build();
+ UnknownFieldSet e =
+ UnknownFieldSet.newBuilder()
+ .addField(1, groupField)
+ .build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(d, e);
+ }
+
+ /**
+ * Asserts that the given field sets are not equal and have different
+ * hash codes.
+ *
+ * @warning It's valid for non-equal objects to have the same hash code, so
+ * this test is stricter than it needs to be. However, this should happen
+ * relatively rarely.
+ */
+ private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
+ String equalsError = String.format("%s should not be equal to %s", s1, s2);
+ assertFalse(equalsError, s1.equals(s2));
+ assertFalse(equalsError, s2.equals(s1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", s1, s2),
+ s1.hashCode() == s2.hashCode());
+ }
+
+ /**
+ * Asserts that the given field sets are equal and have identical hash codes.
+ */
+ private void checkEqualsIsConsistent(UnknownFieldSet set) {
+ // Object should be equal to itself.
+ assertEquals(set, set);
+
+ // Object should be equal to a copy of itself.
+ UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
+ assertEquals(set, copy);
+ assertEquals(copy, set);
+ assertEquals(set.hashCode(), copy.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java
new file mode 100644
index 0000000000..cb75d74b0c
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/UnmodifiableLazyStringListTest.java
@@ -0,0 +1,153 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import junit.framework.TestCase;
+
+import java.util.Iterator;
+import java.util.ListIterator;
+
+/**
+ * Tests for {@link UnmodifiableLazyStringList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testReadOnlyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+ assertEquals(BYTE_STRING_A, list.getByteString(0));
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+ assertEquals(BYTE_STRING_C, list.getByteString(2));
+ }
+
+ public void testModifyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.add(STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.set(1, STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ Iterator<String> iter = list.iterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ }
+
+ public void testListIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ ListIterator<String> iter = list.listIterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.set("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.add("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ }
+
+ private LazyStringArrayList createSampleList() {
+ LazyStringArrayList rawList = new LazyStringArrayList();
+ rawList.add(STRING_A);
+ rawList.add(STRING_B);
+ rawList.add(STRING_C);
+ return rawList;
+ }
+}
diff --git a/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java
new file mode 100644
index 0000000000..7452872620
--- /dev/null
+++ b/third_party/protobuf/java/compatibility_tests/v2.5.0/tests/src/main/java/com/google/protobuf/test/WireFormatTest.java
@@ -0,0 +1,465 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// 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.test;
+import com.google.protobuf.*;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestFieldOrderings;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestMset.TestMessageSet;
+import protobuf_unittest.UnittestMset.RawMessageSet;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+
+/**
+ * Tests related to parsing and serialization.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class WireFormatTest extends TestCase {
+ public void testSerialization() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializationPacked() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testSerializeExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensions() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
+ public void testSerializationPackedWithoutGetSerializedSize()
+ throws Exception {
+ // Write directly to an OutputStream, without invoking getSerializedSize()
+ // This used to be a bug where the size of a packed field was incorrect,
+ // since getSerializedSize() was never invoked.
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ // Directly construct a CodedOutputStream around the actual OutputStream,
+ // in case writeTo(OutputStream output) invokes getSerializedSize();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
+
+ message.writeTo(codedOutput);
+
+ codedOutput.flush();
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(
+ outputStream.toByteArray());
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testParseExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensions message2 =
+ TestAllExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message2);
+ }
+
+ public void testParsePackedExtensions() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestPackedExtensions message2 =
+ TestPackedExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ public void testExtensionsSerializedSize() throws Exception {
+ assertEquals(TestUtil.getAllSet().getSerializedSize(),
+ TestUtil.getAllExtensionsSet().getSerializedSize());
+ }
+
+ public void testSerializeDelimited() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ TestUtil.getAllSet().writeDelimitedTo(output);
+ output.write(12);
+ TestUtil.getPackedSet().writeDelimitedTo(output);
+ output.write(34);
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+
+ TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
+ assertEquals(12, input.read());
+ TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
+ assertEquals(34, input.read());
+ assertEquals(-1, input.read());
+
+ // We're at EOF, so parsing again should return null.
+ assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
+ }
+
+ private void assertFieldsInOrder(ByteString data) throws Exception {
+ CodedInputStream input = data.newCodedInput();
+ int previousTag = 0;
+
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ assertTrue(tag > previousTag);
+ previousTag = tag;
+ input.skipField(tag);
+ }
+ }
+
+ public void testInterleavedFieldsAndExtensions() throws Exception {
+ // Tests that fields are written in order even when extension ranges
+ // are interleaved with field numbers.
+ ByteString data =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build().toByteString();
+ assertFieldsInOrder(data);
+
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ ByteString dynamic_data =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build().toByteString();
+ assertFieldsInOrder(dynamic_data);
+ }
+
+ private ExtensionRegistry getTestFieldOrderingsRegistry() {
+ ExtensionRegistry result = ExtensionRegistry.newInstance();
+ result.add(UnittestProto.myExtensionInt);
+ result.add(UnittestProto.myExtensionString);
+ return result;
+ }
+
+ public void testParseMultipleExtensionRanges() throws Exception {
+ // Make sure we can parse a message that contains multiple extensions
+ // ranges.
+ TestFieldOrderings source =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build();
+ TestFieldOrderings dest =
+ TestFieldOrderings.parseFrom(source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ public void testParseMultipleExtensionRangesDynamic() throws Exception {
+ // Same as above except with DynamicMessage.
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ DynamicMessage source =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build();
+ DynamicMessage dest =
+ DynamicMessage.parseFrom(descriptor, source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ private static final int UNKNOWN_TYPE_ID = 1550055;
+ private static final int TYPE_ID_1 =
+ TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
+ private static final int TYPE_ID_2 =
+ TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
+
+ public void testSerializeMessageSetEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(true);
+ }
+
+ public void testSerializeMessageSetNotEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(false);
+ }
+
+ private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ // Set up a TestMessageSet with two known messages and an unknown one.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(UNKNOWN_TYPE_ID,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build())
+ .build();
+
+ ByteString data = messageSet.toByteString();
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet raw = RawMessageSet.parseFrom(data);
+
+ assertTrue(raw.getUnknownFields().asMap().isEmpty());
+
+ assertEquals(3, raw.getItemCount());
+ assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
+ assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
+ assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
+
+ TestMessageSetExtension1 message1 =
+ TestMessageSetExtension1.parseFrom(
+ raw.getItem(0).getMessage().toByteArray());
+ assertEquals(123, message1.getI());
+
+ TestMessageSetExtension2 message2 =
+ TestMessageSetExtension2.parseFrom(
+ raw.getItem(1).getMessage().toByteArray());
+ assertEquals("foo", message2.getStr());
+
+ assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
+ }
+
+ public void testParseMessageSetEagerly() throws Exception {
+ testParseMessageSetWithFlag(true);
+ }
+
+ public void testParseMessageSetNotEagerly()throws Exception {
+ testParseMessageSetWithFlag(false);
+ }
+
+ private void testParseMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ // Set up a RawMessageSet with two known messages and an unknown one.
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_2)
+ .setMessage(
+ TestMessageSetExtension2.newBuilder()
+ .setStr("foo")
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(UNKNOWN_TYPE_ID)
+ .setMessage(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ // Check for unknown field with type LENGTH_DELIMITED,
+ // number UNKNOWN_TYPE_ID, and contents "bar".
+ UnknownFieldSet unknownFields = messageSet.getUnknownFields();
+ assertEquals(1, unknownFields.asMap().size());
+ assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
+
+ UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
+ }
+
+ public void testParseMessageSetExtensionEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(true);
+ }
+
+ public void testParseMessageSetExtensionNotEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(false);
+ }
+
+ private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and store value into lazy field
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ // Merge lazy field check the contents.
+ messageSet =
+ messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+}
diff --git a/third_party/protobuf/java/core/generate-sources-build.xml b/third_party/protobuf/java/core/generate-sources-build.xml
new file mode 100644
index 0000000000..0996e5fff4
--- /dev/null
+++ b/third_party/protobuf/java/core/generate-sources-build.xml
@@ -0,0 +1,20 @@
+<project name="generate-sources">
+ <echo message="Running protoc ..."/>
+ <mkdir dir="${generated.sources.dir}"/>
+ <exec executable="${protoc}">
+ <arg value="--java_out=${generated.sources.dir}"/>
+ <arg value="--proto_path=${protobuf.source.dir}"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+ </exec>
+</project> \ No newline at end of file
diff --git a/third_party/protobuf/java/core/generate-test-sources-build.xml b/third_party/protobuf/java/core/generate-test-sources-build.xml
new file mode 100644
index 0000000000..ab415db688
--- /dev/null
+++ b/third_party/protobuf/java/core/generate-test-sources-build.xml
@@ -0,0 +1,43 @@
+<project name="generate-test-sources">
+ <mkdir dir="${generated.testsources.dir}"/>
+ <exec executable="${protoc}">
+ <arg value="--java_out=${generated.testsources.dir}"/>
+ <arg value="--proto_path=${protobuf.source.dir}"/>
+ <arg value="--proto_path=${test.proto.dir}"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
+ </exec>
+</project> \ No newline at end of file
diff --git a/third_party/protobuf/java/core/pom.xml b/third_party/protobuf/java/core/pom.xml
new file mode 100644
index 0000000000..be0da5eade
--- /dev/null
+++ b/third_party/protobuf/java/core/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-parent</artifactId>
+ <version>3.2.0</version>
+ </parent>
+
+ <artifactId>protobuf-java</artifactId>
+ <packaging>bundle</packaging>
+
+ <name>Protocol Buffers [Core]</name>
+ <description>
+ Core Protocol Buffers library. Protocol Buffers are a way of encoding structured data in an
+ efficient yet extensible format.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <!-- Include core protos in the bundle as resources -->
+ <resources>
+ <resource>
+ <directory>${protobuf.source.dir}</directory>
+ <includes>
+ <include>google/protobuf/any.proto</include>
+ <include>google/protobuf/api.proto</include>
+ <include>google/protobuf/descriptor.proto</include>
+ <include>google/protobuf/duration.proto</include>
+ <include>google/protobuf/empty.proto</include>
+ <include>google/protobuf/field_mask.proto</include>
+ <include>google/protobuf/source_context.proto</include>
+ <include>google/protobuf/struct.proto</include>
+ <include>google/protobuf/timestamp.proto</include>
+ <include>google/protobuf/type.proto</include>
+ <include>google/protobuf/wrappers.proto</include>
+ <include>google/protobuf/compiler/plugin.proto</include>
+ </includes>
+ </resource>
+ </resources>
+
+ <plugins>
+ <!-- Use Antrun plugin to generate sources with protoc -->
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <!-- Generate core protos -->
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <target>
+ <ant antfile="generate-sources-build.xml"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <!-- Generate the test protos -->
+ <execution>
+ <id>generate-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <configuration>
+ <target>
+ <ant antfile="generate-test-sources-build.xml"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Add the generated sources to the build -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-generated-sources</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${generated.sources.dir}</source>
+ </sources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>add-generated-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${generated.testsources.dir}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- OSGI bundle configuration -->
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+ <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
+ <Export-Package>com.google.protobuf;version=${project.version}</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
new file mode 100644
index 0000000000..37180da857
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -0,0 +1,649 @@
+// 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 com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Internal.EnumLite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A partial implementation of the {@link Message} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessage
+ // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+ extends AbstractMessageLite
+ implements Message {
+
+ @Override
+ public boolean isInitialized() {
+ return MessageReflection.isInitialized(this);
+ }
+
+ /**
+ * Interface for the parent of a Builder that allows the builder to
+ * communicate invalidations back to the parent for use when using nested
+ * builders.
+ */
+ protected interface BuilderParent {
+
+ /**
+ * A builder becomes dirty whenever a field is modified -- including fields
+ * in nested builders -- and becomes clean when build() is called. Thus,
+ * when a builder becomes dirty, all its parents become dirty as well, and
+ * when it becomes clean, all its children become clean. The dirtiness
+ * state is used to invalidate certain cached values.
+ * <br>
+ * To this end, a builder calls markDirty() on its parent whenever it
+ * transitions from clean to dirty. The parent must propagate this call to
+ * its own parent, unless it was already dirty, in which case the
+ * grandparent must necessarily already be dirty as well. The parent can
+ * only transition back to "clean" after calling build() on all children.
+ */
+ void markDirty();
+ }
+
+ /** Create a nested builder. */
+ protected Message.Builder newBuilderForType(BuilderParent parent) {
+ throw new UnsupportedOperationException("Nested builder is not supported for this type.");
+ }
+
+
+ @Override
+ public List<String> findInitializationErrors() {
+ return MessageReflection.findMissingFields(this);
+ }
+
+ @Override
+ public String getInitializationErrorString() {
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
+ }
+
+ @Override
+ public final String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ @Override
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ MessageReflection.writeMessageTo(this, getAllFields(), output, false);
+ }
+
+ protected int memoizedSize = -1;
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(this, getAllFields());
+ return memoizedSize;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Message)) {
+ return false;
+ }
+ final Message otherMessage = (Message) other;
+ if (getDescriptorForType() != otherMessage.getDescriptorForType()) {
+ return false;
+ }
+ return compareFields(getAllFields(), otherMessage.getAllFields()) &&
+ getUnknownFields().equals(otherMessage.getUnknownFields());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = memoizedHashCode;
+ if (hash == 0) {
+ hash = 41;
+ hash = (19 * hash) + getDescriptorForType().hashCode();
+ hash = hashFields(hash, getAllFields());
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ }
+ return hash;
+ }
+
+ private static ByteString toByteString(Object value) {
+ if (value instanceof byte[]) {
+ return ByteString.copyFrom((byte[]) value);
+ } else {
+ return (ByteString) value;
+ }
+ }
+
+ /**
+ * Compares two bytes fields. The parameters must be either a byte array or a
+ * ByteString object. They can be of different type though.
+ */
+ private static boolean compareBytes(Object a, Object b) {
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[])a, (byte[])b);
+ }
+ return toByteString(a).equals(toByteString(b));
+ }
+
+ /**
+ * Converts a list of MapEntry messages into a Map used for equals() and
+ * hashCode().
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static Map convertMapEntryListToMap(List list) {
+ if (list.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ Map result = new HashMap();
+ Iterator iterator = list.iterator();
+ Message entry = (Message) iterator.next();
+ Descriptors.Descriptor descriptor = entry.getDescriptorForType();
+ Descriptors.FieldDescriptor key = descriptor.findFieldByName("key");
+ Descriptors.FieldDescriptor value = descriptor.findFieldByName("value");
+ Object fieldValue = entry.getField(value);
+ if (fieldValue instanceof EnumValueDescriptor) {
+ fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+ }
+ result.put(entry.getField(key), fieldValue);
+ while (iterator.hasNext()) {
+ entry = (Message) iterator.next();
+ fieldValue = entry.getField(value);
+ if (fieldValue instanceof EnumValueDescriptor) {
+ fieldValue = ((EnumValueDescriptor) fieldValue).getNumber();
+ }
+ result.put(entry.getField(key), fieldValue);
+ }
+ return result;
+ }
+
+ /**
+ * Compares two map fields. The parameters must be a list of MapEntry
+ * messages.
+ */
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static boolean compareMapField(Object a, Object b) {
+ Map ma = convertMapEntryListToMap((List) a);
+ Map mb = convertMapEntryListToMap((List) b);
+ return MapFieldLite.equals(ma, mb);
+ }
+
+ /**
+ * Compares two set of fields.
+ * This method is used to implement {@link AbstractMessage#equals(Object)}
+ * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
+ * of bytes fields because immutable messages and mutable messages use
+ * different Java type to reprensent a bytes field and this method should be
+ * able to compare immutable messages, mutable messages and also an immutable
+ * message to a mutable message.
+ */
+ static boolean compareFields(Map<FieldDescriptor, Object> a,
+ Map<FieldDescriptor, Object> b) {
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (FieldDescriptor descriptor : a.keySet()) {
+ if (!b.containsKey(descriptor)) {
+ return false;
+ }
+ Object value1 = a.get(descriptor);
+ Object value2 = b.get(descriptor);
+ if (descriptor.getType() == FieldDescriptor.Type.BYTES) {
+ if (descriptor.isRepeated()) {
+ List list1 = (List) value1;
+ List list2 = (List) value2;
+ if (list1.size() != list2.size()) {
+ return false;
+ }
+ for (int i = 0; i < list1.size(); i++) {
+ if (!compareBytes(list1.get(i), list2.get(i))) {
+ return false;
+ }
+ }
+ } else {
+ // Compares a singular bytes field.
+ if (!compareBytes(value1, value2)) {
+ return false;
+ }
+ }
+ } else if (descriptor.isMapField()) {
+ if (!compareMapField(value1, value2)) {
+ return false;
+ }
+ } else {
+ // Compare non-bytes fields.
+ if (!value1.equals(value2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Calculates the hash code of a map field. {@code value} must be a list of
+ * MapEntry messages.
+ */
+ @SuppressWarnings("unchecked")
+ private static int hashMapField(Object value) {
+ return MapFieldLite.calculateHashCodeForMap(convertMapEntryListToMap((List) value));
+ }
+
+ /** Get a hash code for given fields and values, using the given seed. */
+ @SuppressWarnings("unchecked")
+ protected static int hashFields(int hash, Map<FieldDescriptor, Object> map) {
+ for (Map.Entry<FieldDescriptor, Object> entry : map.entrySet()) {
+ FieldDescriptor field = entry.getKey();
+ Object value = entry.getValue();
+ hash = (37 * hash) + field.getNumber();
+ if (field.isMapField()) {
+ hash = (53 * hash) + hashMapField(value);
+ } else if (field.getType() != FieldDescriptor.Type.ENUM){
+ hash = (53 * hash) + value.hashCode();
+ } else if (field.isRepeated()) {
+ List<? extends EnumLite> list = (List<? extends EnumLite>) value;
+ hash = (53 * hash) + Internal.hashEnumList(list);
+ } else {
+ hash = (53 * hash) + Internal.hashEnum((EnumLite) value);
+ }
+ }
+ return hash;
+ }
+
+ /**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException with missing field information.
+ */
+ @Override
+ UninitializedMessageException newUninitializedMessageException() {
+ return Builder.newUninitializedMessageException(this);
+ }
+
+ // =================================================================
+
+ /**
+ * A partial implementation of the {@link Message.Builder} interface which
+ * implements as many methods of that interface as possible in terms of
+ * other methods.
+ */
+ @SuppressWarnings("unchecked")
+ public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+ extends AbstractMessageLite.Builder
+ implements Message.Builder {
+ // The compiler produces an error if this is not declared explicitly.
+ // Method isn't abstract to bypass Java 1.6 compiler issue http://bugs.java.com/view_bug.do?bug_id=6908259
+ @Override
+ public BuilderType clone() {
+ throw new UnsupportedOperationException("clone() should be implemented in subclasses.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("hasOneof() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException(
+ "getOneofFieldDescriptor() is not implemented.");
+ }
+
+ /** TODO(jieluo): Clear it when all subclasses have implemented this method. */
+ @Override
+ public BuilderType clearOneof(OneofDescriptor oneof) {
+ throw new UnsupportedOperationException("clearOneof() is not implemented.");
+ }
+
+ @Override
+ public BuilderType clear() {
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ getAllFields().entrySet()) {
+ clearField(entry.getKey());
+ }
+ return (BuilderType) this;
+ }
+
+ @Override
+ public List<String> findInitializationErrors() {
+ return MessageReflection.findMissingFields(this);
+ }
+
+ @Override
+ public String getInitializationErrorString() {
+ return MessageReflection.delimitWithCommas(findInitializationErrors());
+ }
+
+ @Override
+ protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+ return mergeFrom((Message) other);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final Message other) {
+ if (other.getDescriptorForType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "mergeFrom(Message) can only merge messages of the same type.");
+ }
+
+ // Note: We don't attempt to verify that other's fields have valid
+ // types. Doing so would be a losing battle. We'd have to verify
+ // all sub-messages as well, and we'd have to make copies of all of
+ // them to insure that they don't change after verification (since
+ // the Message interface itself cannot enforce immutability of
+ // implementations).
+ // TODO(kenton): Provide a function somewhere called makeDeepCopy()
+ // which allows people to make secure deep copies of messages.
+
+ for (final Map.Entry<FieldDescriptor, Object> entry :
+ other.getAllFields().entrySet()) {
+ final FieldDescriptor field = entry.getKey();
+ if (field.isRepeated()) {
+ for (final Object element : (List)entry.getValue()) {
+ addRepeatedField(field, element);
+ }
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ final Message existingValue = (Message)getField(field);
+ if (existingValue == existingValue.getDefaultInstanceForType()) {
+ setField(field, entry.getValue());
+ } else {
+ setField(field,
+ existingValue.newBuilderForType()
+ .mergeFrom(existingValue)
+ .mergeFrom((Message)entry.getValue())
+ .build());
+ }
+ } else {
+ setField(field, entry.getValue());
+ }
+ }
+
+ mergeUnknownFields(other.getUnknownFields());
+
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input)
+ throws IOException {
+ return mergeFrom(input, ExtensionRegistry.getEmptyRegistry());
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final CodedInputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final UnknownFieldSet.Builder unknownFields =
+ UnknownFieldSet.newBuilder(getUnknownFields());
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ MessageReflection.BuilderAdapter builderAdapter =
+ new MessageReflection.BuilderAdapter(this);
+ if (!MessageReflection.mergeFieldFrom(input, unknownFields,
+ extensionRegistry,
+ getDescriptorForType(),
+ builderAdapter,
+ tag)) {
+ // end group tag
+ break;
+ }
+ }
+ setUnknownFields(unknownFields.build());
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
+ setUnknownFields(
+ UnknownFieldSet.newBuilder(getUnknownFields())
+ .mergeFrom(unknownFields)
+ .build());
+ return (BuilderType) this;
+ }
+
+ @Override
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on an unsupported message type.");
+ }
+
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on an unsupported message type.");
+ }
+
+ @Override
+ public String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(Message message) {
+ return new UninitializedMessageException(
+ MessageReflection.findMissingFields(message));
+ }
+
+ /**
+ * Used to support nested builders and called to mark this builder as clean.
+ * Clean builders will propagate the {@link BuilderParent#markDirty()} event
+ * to their parent builders, while dirty builders will not, as their parents
+ * should be dirty already.
+ *
+ * NOTE: Implementations that don't support nested builders don't need to
+ * override this method.
+ */
+ void markClean() {
+ throw new IllegalStateException("Should be overridden by subclasses.");
+ }
+
+ /**
+ * Used to support nested builders and called when this nested builder is
+ * no longer used by its parent builder and should release the reference
+ * to its parent builder.
+ *
+ * NOTE: Implementations that don't support nested builders don't need to
+ * override this method.
+ */
+ void dispose() {
+ throw new IllegalStateException("Should be overridden by subclasses.");
+ }
+
+ // ===============================================================
+ // The following definitions seem to be required in order to make javac
+ // not produce weird errors like:
+ //
+ // java/com/google/protobuf/DynamicMessage.java:203: types
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> and
+ // com.google.protobuf.AbstractMessage.Builder<
+ // com.google.protobuf.DynamicMessage.Builder> are incompatible; both
+ // define mergeFrom(com.google.protobuf.ByteString), but with unrelated
+ // return types.
+ //
+ // Strangely, these lines are only needed if javac is invoked separately
+ // on AbstractMessage.java and AbstractMessageLite.java. If javac is
+ // invoked on both simultaneously, it works. (Or maybe the important
+ // point is whether or not DynamicMessage.java is compiled together with
+ // AbstractMessageLite.java -- not sure.) I suspect this is a compiler
+ // bug.
+
+ @Override
+ public BuilderType mergeFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final ByteString data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, off, len);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data, final int off, final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final InputStream input)
+ throws IOException {
+ return (BuilderType) super.mergeFrom(input);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return (BuilderType) super.mergeFrom(input, extensionRegistry);
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(final InputStream input)
+ throws IOException {
+ return super.mergeDelimitedFrom(input);
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(
+ final InputStream input,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return super.mergeDelimitedFrom(input, extensionRegistry);
+ }
+ }
+
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashLong(long n) {
+ return (int) (n ^ (n >>> 32));
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashBoolean(boolean b) {
+ return b ? 1231 : 1237;
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashEnum(EnumLite e) {
+ return e.getNumber();
+ }
+ //
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
+ * generated code.
+ */
+ @Deprecated
+ protected static int hashEnumList(List<? extends EnumLite> list) {
+ int hash = 1;
+ for (EnumLite e : list) {
+ hash = 31 * hash + hashEnum(e);
+ }
+ return hash;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
new file mode 100644
index 0000000000..4f691dfdfb
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -0,0 +1,383 @@
+// 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.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collection;
+
+/**
+ * A partial implementation of the {@link MessageLite} interface which
+ * implements as many methods of that interface as possible in terms of other
+ * methods.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class AbstractMessageLite<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
+ implements MessageLite {
+ protected int memoizedHashCode = 0;
+ @Override
+ public ByteString toByteString() {
+ try {
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize());
+ writeTo(out.getCodedOutput());
+ return out.build();
+ } catch (IOException e) {
+ throw new RuntimeException(getSerializingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ try {
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeTo(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (IOException e) {
+ throw new RuntimeException(getSerializingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public void writeTo(final OutputStream output) throws IOException {
+ final int bufferSize =
+ CodedOutputStream.computePreferredBufferSize(getSerializedSize());
+ final CodedOutputStream codedOutput =
+ CodedOutputStream.newInstance(output, bufferSize);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ @Override
+ public void writeDelimitedTo(final OutputStream output) throws IOException {
+ final int serialized = getSerializedSize();
+ final int bufferSize = CodedOutputStream.computePreferredBufferSize(
+ CodedOutputStream.computeRawVarint32Size(serialized) + serialized);
+ final CodedOutputStream codedOutput =
+ CodedOutputStream.newInstance(output, bufferSize);
+ codedOutput.writeRawVarint32(serialized);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+
+ /**
+ * Package private helper method for AbstractParser to create
+ * UninitializedMessageException.
+ */
+ UninitializedMessageException newUninitializedMessageException() {
+ return new UninitializedMessageException(this);
+ }
+
+ private String getSerializingExceptionMessage(String target) {
+ return "Serializing " + getClass().getName() + " to a " + target
+ + " threw an IOException (should never happen).";
+ }
+
+ protected static void checkByteStringIsUtf8(ByteString byteString)
+ throws IllegalArgumentException {
+ if (!byteString.isValidUtf8()) {
+ throw new IllegalArgumentException("Byte string is not UTF-8.");
+ }
+ }
+
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ Builder.addAll(values, list);
+ }
+
+ /**
+ * A partial implementation of the {@link Message.Builder} interface which
+ * implements as many methods of that interface as possible in terms of
+ * other methods.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends Builder<MessageType, BuilderType>>
+ implements MessageLite.Builder {
+ // The compiler produces an error if this is not declared explicitly.
+ @Override
+ public abstract BuilderType clone();
+
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
+ return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ // Re-defined here for return type covariance.
+ @Override
+ public abstract BuilderType mergeFrom(
+ final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ @Override
+ public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final ByteString data, final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("ByteString"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+ return mergeFrom(data, 0, data.length);
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return mergeFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final byte[] data,
+ final int off,
+ final int len,
+ final ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input, extensionRegistry);
+ input.checkLastTagWas(0);
+ return (BuilderType) this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(getReadingExceptionMessage("byte array"), e);
+ }
+ }
+
+ @Override
+ public BuilderType mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput, extensionRegistry);
+ codedInput.checkLastTagWas(0);
+ return (BuilderType) this;
+ }
+
+ /**
+ * An InputStream implementations which reads from some other InputStream
+ * but is limited to a particular number of bytes. Used by
+ * mergeDelimitedFrom(). This is intentionally package-private so that
+ * UnknownFieldSet can share it.
+ */
+ static final class LimitedInputStream extends FilterInputStream {
+ private int limit;
+
+ LimitedInputStream(InputStream in, int limit) {
+ super(in);
+ this.limit = limit;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return Math.min(super.available(), limit);
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ final int result = super.read();
+ if (result >= 0) {
+ --limit;
+ }
+ return result;
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, int len)
+ throws IOException {
+ if (limit <= 0) {
+ return -1;
+ }
+ len = Math.min(len, limit);
+ final int result = super.read(b, off, len);
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ final long result = super.skip(Math.min(n, limit));
+ if (result >= 0) {
+ limit -= result;
+ }
+ return result;
+ }
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ mergeFrom(limitedInput, extensionRegistry);
+ return true;
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
+ return mergeDelimitedFrom(input,
+ ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // isInstance takes care of this
+ public BuilderType mergeFrom(final MessageLite other) {
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ throw new IllegalArgumentException(
+ "mergeFrom(MessageLite) can only merge messages of the same type.");
+ }
+
+ return internalMergeFrom((MessageType) other);
+ }
+
+ protected abstract BuilderType internalMergeFrom(MessageType message);
+
+ private String getReadingExceptionMessage(String target) {
+ return "Reading " + getClass().getName() + " from a " + target
+ + " threw an IOException (should never happen).";
+ }
+
+ /**
+ * Construct an UninitializedMessageException reporting missing fields in
+ * the given message.
+ */
+ protected static UninitializedMessageException
+ newUninitializedMessageException(MessageLite message) {
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Adds the {@code values} to the {@code list}. This is a helper method
+ * used by generated code. Users should ignore it.
+ *
+ * @throws NullPointerException if {@code values} or any of the elements of
+ * {@code values} is null. When that happens, some elements of
+ * {@code values} may have already been added to the result {@code list}.
+ */
+ protected static <T> void addAll(final Iterable<T> values,
+ final Collection<? super T> list) {
+ if (values == null) {
+ throw new NullPointerException();
+ }
+ if (values instanceof LazyStringList) {
+ // For StringOrByteStringLists, check the underlying elements to avoid
+ // forcing conversions of ByteStrings to Strings.
+ checkForNullValues(((LazyStringList) values).getUnderlyingElements());
+ list.addAll((Collection<T>) values);
+ } else if (values instanceof Collection) {
+ checkForNullValues(values);
+ list.addAll((Collection<T>) values);
+ } else {
+ for (final T value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ list.add(value);
+ }
+ }
+ }
+
+ private static void checkForNullValues(final Iterable<?> values) {
+ for (final Object value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractParser.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractParser.java
new file mode 100644
index 0000000000..7ff73ba4d1
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractParser.java
@@ -0,0 +1,258 @@
+// 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 com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A partial implementation of the {@link Parser} interface which implements
+ * as many methods of that interface as possible in terms of other methods.
+ *
+ * Note: This class implements all the convenience methods in the
+ * {@link Parser} interface. See {@link Parser} for related javadocs.
+ * Subclasses need to implement
+ * {@link Parser#parsePartialFrom(CodedInputStream, ExtensionRegistryLite)}
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public abstract class AbstractParser<MessageType extends MessageLite>
+ implements Parser<MessageType> {
+ /**
+ * Creates an UninitializedMessageException for MessageType.
+ */
+ private UninitializedMessageException
+ newUninitializedMessageException(MessageType message) {
+ if (message instanceof AbstractMessageLite) {
+ return ((AbstractMessageLite) message).newUninitializedMessageException();
+ }
+ return new UninitializedMessageException(message);
+ }
+
+ /**
+ * Helper method to check if message is initialized.
+ *
+ * @throws InvalidProtocolBufferException if it is not initialized.
+ * @return The message to check.
+ */
+ private MessageType checkMessageInitialized(MessageType message)
+ throws InvalidProtocolBufferException {
+ if (message != null && !message.isInitialized()) {
+ throw newUninitializedMessageException(message)
+ .asInvalidProtocolBufferException()
+ .setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ private static final ExtensionRegistryLite EMPTY_REGISTRY
+ = ExtensionRegistryLite.getEmptyRegistry();
+
+ @Override
+ public MessageType parsePartialFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ MessageType message;
+ try {
+ CodedInputStream input = data.newCodedInput();
+ message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data, off, len);
+ MessageType message = parsePartialFrom(input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
+ return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(data, off, len, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, off, len, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return parseFrom(data, 0, data.length, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
+ return parseFrom(data, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ MessageType message = parsePartialFrom(codedInput, extensionRegistry);
+ try {
+ codedInput.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ @Override
+ public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parsePartialFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parseFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parsePartialDelimitedFrom(
+ InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ int size;
+ try {
+ int firstByte = input.read();
+ if (firstByte == -1) {
+ return null;
+ }
+ size = CodedInputStream.readRawVarint32(firstByte, input);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e);
+ }
+ InputStream limitedInput = new LimitedInputStream(input, size);
+ return parsePartialFrom(limitedInput, extensionRegistry);
+ }
+
+ @Override
+ public MessageType parsePartialDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialDelimitedFrom(input, extensionRegistry));
+ }
+
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
+ return parseDelimitedFrom(input, EMPTY_REGISTRY);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
new file mode 100644
index 0000000000..b17db6e0b3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -0,0 +1,180 @@
+// 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 com.google.protobuf.Internal.ProtobufList;
+
+import java.util.AbstractList;
+import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
+ * {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
+ */
+abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+
+ protected static final int DEFAULT_CAPACITY = 10;
+
+ /**
+ * Whether or not this list is modifiable.
+ */
+ private boolean isMutable;
+
+ /**
+ * Constructs a mutable list by default.
+ */
+ AbstractProtobufList() {
+ isMutable = true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof List)) {
+ return false;
+ }
+ // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+ // based approach in our super class. Otherwise our index based approach will avoid those
+ // allocations.
+ if (!(o instanceof RandomAccess)) {
+ return super.equals(o);
+ }
+
+ List<?> other = (List<?>) o;
+ final int size = size();
+ if (size != other.size()) {
+ return false;
+ }
+ for (int i = 0; i < size; i++) {
+ if (!get(i).equals(other.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int size = size();
+ int hashCode = 1;
+ for (int i = 0; i < size; i++) {
+ hashCode = (31 * hashCode) + get(i).hashCode();
+ }
+ return hashCode;
+ }
+
+ @Override
+ public boolean add(E e) {
+ ensureIsMutable();
+ return super.add(e);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ ensureIsMutable();
+ super.add(index, element);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(c);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends E> c) {
+ ensureIsMutable();
+ return super.addAll(index, c);
+ }
+
+ @Override
+ public void clear() {
+ ensureIsMutable();
+ super.clear();
+ }
+
+ @Override
+ public boolean isModifiable() {
+ return isMutable;
+ }
+
+ @Override
+ public final void makeImmutable() {
+ isMutable = false;
+ }
+
+ @Override
+ public E remove(int index) {
+ ensureIsMutable();
+ return super.remove(index);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ return super.remove(o);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ ensureIsMutable();
+ return super.retainAll(c);
+ }
+
+ @Override
+ public E set(int index, E element) {
+ ensureIsMutable();
+ return super.set(index, element);
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if the list is immutable. Subclasses are
+ * responsible for invoking this method on mutate operations.
+ */
+ protected void ensureIsMutable() {
+ if (!isMutable) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java
new file mode 100644
index 0000000000..d535efb9b6
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java
@@ -0,0 +1,51 @@
+// 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;
+
+/**
+ * <p>Abstract interface for a blocking RPC channel. {@code BlockingRpcChannel}
+ * is the blocking equivalent to {@link RpcChannel}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingRpcChannel {
+ /**
+ * Call the given method of the remote service and blocks until it returns.
+ * {@code callBlockingMethod()} is the blocking equivalent to
+ * {@link RpcChannel#callMethod}.
+ */
+ Message callBlockingMethod(
+ Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request,
+ Message responsePrototype) throws ServiceException;
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingService.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingService.java
new file mode 100644
index 0000000000..d01f0b8ff0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BlockingService.java
@@ -0,0 +1,64 @@
+// 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;
+
+/**
+ * Blocking equivalent to {@link Service}.
+ *
+ * @author kenton@google.com Kenton Varda
+ * @author cpovirk@google.com Chris Povirk
+ */
+public interface BlockingService {
+ /**
+ * Equivalent to {@link Service#getDescriptorForType}.
+ */
+ Descriptors.ServiceDescriptor getDescriptorForType();
+
+ /**
+ * Equivalent to {@link Service#callMethod}, except that
+ * {@code callBlockingMethod()} returns the result of the RPC or throws a
+ * {@link ServiceException} if there is a failure, rather than passing the
+ * information to a callback.
+ */
+ Message callBlockingMethod(Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request) throws ServiceException;
+
+ /**
+ * Equivalent to {@link Service#getRequestPrototype}.
+ */
+ Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+ /**
+ * Equivalent to {@link Service#getResponsePrototype}.
+ */
+ Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
new file mode 100644
index 0000000000..0d9f87ba01
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -0,0 +1,272 @@
+// 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 com.google.protobuf.Internal.BooleanList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link BooleanList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class BooleanArrayList
+ extends AbstractProtobufList<Boolean>
+ implements BooleanList, RandomAccess {
+
+ private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static BooleanArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private boolean[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code BooleanArrayList} with default capacity.
+ */
+ BooleanArrayList() {
+ this(new boolean[DEFAULT_CAPACITY], 0);
+ }
+
+ /**
+ * Constructs a new mutable {@code BooleanArrayList}
+ * containing the same elements as {@code other}.
+ */
+ private BooleanArrayList(boolean[] other, int size) {
+ array = other;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof BooleanArrayList)) {
+ return super.equals(o);
+ }
+ BooleanArrayList other = (BooleanArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final boolean[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Internal.hashBoolean(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public BooleanList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new BooleanArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
+ @Override
+ public Boolean get(int index) {
+ return getBoolean(index);
+ }
+
+ @Override
+ public boolean getBoolean(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Boolean set(int index, Boolean element) {
+ return setBoolean(index, element);
+ }
+
+ @Override
+ public boolean setBoolean(int index, boolean element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ boolean previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Boolean element) {
+ addBoolean(index, element);
+ }
+
+ /**
+ * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addBoolean(boolean element) {
+ addBoolean(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Boolean)} but more efficient in that it doesn't box the element.
+ */
+ private void addBoolean(int index, boolean element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ boolean[] newArray = new boolean[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Boolean> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another BooleanArrayList to avoid boxing elements.
+ if (!(collection instanceof BooleanArrayList)) {
+ return super.addAll(collection);
+ }
+
+ BooleanArrayList list = (BooleanArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Boolean remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ boolean value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
new file mode 100644
index 0000000000..6157a52f50
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
@@ -0,0 +1,185 @@
+// 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 static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+/**
+ * Utility class to provide efficient writing of {@link ByteBuffer}s to {@link OutputStream}s.
+ */
+final class ByteBufferWriter {
+ private ByteBufferWriter() {}
+
+ /**
+ * Minimum size for a cached buffer. This prevents us from allocating buffers that are too
+ * small to be easily reused.
+ */
+ // TODO(nathanmittler): tune this property or allow configuration?
+ private static final int MIN_CACHED_BUFFER_SIZE = 1024;
+
+ /**
+ * Maximum size for a cached buffer. If a larger buffer is required, it will be allocated
+ * but not cached.
+ */
+ // TODO(nathanmittler): tune this property or allow configuration?
+ private static final int MAX_CACHED_BUFFER_SIZE = 16 * 1024;
+
+ /**
+ * The fraction of the requested buffer size under which the buffer will be reallocated.
+ */
+ // TODO(nathanmittler): tune this property or allow configuration?
+ private static final float BUFFER_REALLOCATION_THRESHOLD = 0.5f;
+
+ /**
+ * Keeping a soft reference to a thread-local buffer. This buffer is used for writing a
+ * {@link ByteBuffer} to an {@link OutputStream} when no zero-copy alternative was available.
+ * Using a "soft" reference since VMs may keep this reference around longer than "weak"
+ * (e.g. HotSpot will maintain soft references until memory pressure warrants collection).
+ */
+ private static final ThreadLocal<SoftReference<byte[]>> BUFFER =
+ new ThreadLocal<SoftReference<byte[]>>();
+
+ /**
+ * This is a hack for GAE, where {@code FileOutputStream} is unavailable.
+ */
+ private static final Class<?> FILE_OUTPUT_STREAM_CLASS = safeGetClass("java.io.FileOutputStream");
+ private static final long CHANNEL_FIELD_OFFSET = getChannelFieldOffset(FILE_OUTPUT_STREAM_CLASS);
+
+ /**
+ * For testing purposes only. Clears the cached buffer to force a new allocation on the next
+ * invocation.
+ */
+ static void clearCachedBuffer() {
+ BUFFER.set(null);
+ }
+
+ /**
+ * Writes the remaining content of the buffer to the given stream. The buffer {@code position}
+ * will remain unchanged by this method.
+ */
+ static void write(ByteBuffer buffer, OutputStream output) throws IOException {
+ final int initialPos = buffer.position();
+ try {
+ if (buffer.hasArray()) {
+ // Optimized write for array-backed buffers.
+ // Note that we're taking the risk that a malicious OutputStream could modify the array.
+ output.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
+ } else if (!writeToChannel(buffer, output)){
+ // Read all of the data from the buffer to an array.
+ // TODO(nathanmittler): Consider performance improvements for other "known" stream types.
+ final byte[] array = getOrCreateBuffer(buffer.remaining());
+ while (buffer.hasRemaining()) {
+ int length = min(buffer.remaining(), array.length);
+ buffer.get(array, 0, length);
+ output.write(array, 0, length);
+ }
+ }
+ } finally {
+ // Restore the initial position.
+ buffer.position(initialPos);
+ }
+ }
+
+ private static byte[] getOrCreateBuffer(int requestedSize) {
+ requestedSize = max(requestedSize, MIN_CACHED_BUFFER_SIZE);
+
+ byte[] buffer = getBuffer();
+ // Only allocate if we need to.
+ if (buffer == null || needToReallocate(requestedSize, buffer.length)) {
+ buffer = new byte[requestedSize];
+
+ // Only cache the buffer if it's not too big.
+ if (requestedSize <= MAX_CACHED_BUFFER_SIZE) {
+ setBuffer(buffer);
+ }
+ }
+ return buffer;
+ }
+
+ private static boolean needToReallocate(int requestedSize, int bufferLength) {
+ // First check against just the requested length to avoid the multiply.
+ return bufferLength < requestedSize
+ && bufferLength < requestedSize * BUFFER_REALLOCATION_THRESHOLD;
+ }
+
+ private static byte[] getBuffer() {
+ SoftReference<byte[]> sr = BUFFER.get();
+ return sr == null ? null : sr.get();
+ }
+
+ private static void setBuffer(byte[] value) {
+ BUFFER.set(new SoftReference<byte[]>(value));
+ }
+
+ private static boolean writeToChannel(ByteBuffer buffer, OutputStream output) throws IOException {
+ if (CHANNEL_FIELD_OFFSET >= 0 && FILE_OUTPUT_STREAM_CLASS.isInstance(output)) {
+ // Use a channel to write out the ByteBuffer. This will automatically empty the buffer.
+ WritableByteChannel channel = null;
+ try {
+ channel = (WritableByteChannel) UnsafeUtil.getObject(output, CHANNEL_FIELD_OFFSET);
+ } catch (ClassCastException e) {
+ // Absorb.
+ }
+ if (channel != null) {
+ channel.write(buffer);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static Class<?> safeGetClass(String className) {
+ try {
+ return Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+ private static long getChannelFieldOffset(Class<?> clazz) {
+ try {
+ if (clazz != null && UnsafeUtil.hasUnsafeArrayOperations()) {
+ Field field = clazz.getDeclaredField("channel");
+ return UnsafeUtil.objectFieldOffset(field);
+ }
+ } catch (Throwable e) {
+ // Absorb
+ }
+ return -1;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteOutput.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteOutput.java
new file mode 100644
index 0000000000..ee5887538f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteOutput.java
@@ -0,0 +1,116 @@
+// 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.nio.ByteBuffer;
+
+/**
+ * An output target for raw bytes. This interface provides semantics that support two types of
+ * writing:
+ *
+ * <p><b>Traditional write operations:</b>
+ * (as defined by {@link java.io.OutputStream}) where the target method is responsible for either
+ * copying the data or completing the write before returning from the method call.
+ *
+ * <p><b>Lazy write operations:</b> where the caller guarantees that it will never modify the
+ * provided buffer and it can therefore be considered immutable. The target method is free to
+ * maintain a reference to the buffer beyond the scope of the method call (e.g. until the write
+ * operation completes).
+ */
+@ExperimentalApi
+public abstract class ByteOutput {
+ /**
+ * Writes a single byte.
+ *
+ * @param value the byte to be written
+ * @throws IOException thrown if an error occurred while writing
+ */
+ public abstract void write(byte value) throws IOException;
+
+ /**
+ * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will
+ * not be processed prior to the return of this method call, since {@code value} may be
+ * reused/altered by the caller.
+ *
+ * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+ * programming error and will lead to data corruption which will be difficult to debug.
+ *
+ * @param value the bytes to be written
+ * @param offset the offset of the start of the writable range
+ * @param length the number of bytes to write starting from {@code offset}
+ * @throws IOException thrown if an error occurred while writing
+ */
+ public abstract void write(byte[] value, int offset, int length) throws IOException;
+
+ /**
+ * Writes a sequence of bytes. The {@link ByteOutput} is free to retain a reference to the value
+ * beyond the scope of this method call (e.g. write later) since it is considered immutable and is
+ * guaranteed not to change by the caller.
+ *
+ * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+ * programming error and will lead to data corruption which will be difficult to debug.
+ *
+ * @param value the bytes to be written
+ * @param offset the offset of the start of the writable range
+ * @param length the number of bytes to write starting from {@code offset}
+ * @throws IOException thrown if an error occurred while writing
+ */
+ public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
+
+ /**
+ * Writes a sequence of bytes. The {@link ByteOutput} must copy {@code value} if it will
+ * not be processed prior to the return of this method call, since {@code value} may be
+ * reused/altered by the caller.
+ *
+ * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+ * programming error and will lead to data corruption which will be difficult to debug.
+ *
+ * @param value the bytes to be written. Upon returning from this call, the {@code position} of
+ * this buffer will be set to the {@code limit}
+ * @throws IOException thrown if an error occurred while writing
+ */
+ public abstract void write(ByteBuffer value) throws IOException;
+
+ /**
+ * Writes a sequence of bytes. The {@link ByteOutput} is free to retain a reference to the value
+ * beyond the scope of this method call (e.g. write later) since it is considered immutable and is
+ * guaranteed not to change by the caller.
+ *
+ * <p>NOTE: This method <strong>MUST NOT</strong> modify the {@code value}. Doing so is a
+ * programming error and will lead to data corruption which will be difficult to debug.
+ *
+ * @param value the bytes to be written. Upon returning from this call, the {@code position} of
+ * this buffer will be set to the {@code limit}
+ * @throws IOException thrown if an error occurred while writing
+ */
+ public abstract void writeLazy(ByteBuffer value) throws IOException;
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteString.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteString.java
new file mode 100644
index 0000000000..99a312096d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -0,0 +1,1558 @@
+// 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.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;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * Immutable sequence of bytes. Substring is supported by sharing the reference to the immutable
+ * underlying bytes. Concatenation is likewise supported without copying (long strings) by building
+ * a tree of pieces in {@link RopeByteString}.
+ *
+ * <p>Like {@link String}, the contents of a {@link ByteString} can never be observed to change, not
+ * even in the presence of a data race or incorrect API usage in the client code.
+ *
+ * @author crazybob@google.com Bob Lee
+ * @author kenton@google.com Kenton Varda
+ * @author carlanton@google.com Carl Haverl
+ * @author martinrb@google.com Martin Buchholz
+ */
+public abstract class ByteString implements Iterable<Byte>, Serializable {
+
+ /**
+ * When two strings to be concatenated have a combined length shorter than
+ * this, we just copy their bytes on {@link #concat(ByteString)}.
+ * The trade-off is copy size versus the overhead of creating tree nodes
+ * in {@link RopeByteString}.
+ */
+ static final int CONCATENATE_BY_COPY_SIZE = 128;
+
+ /**
+ * When copying an InputStream into a ByteString with .readFrom(),
+ * the chunks in the underlying rope start at 256 bytes, but double
+ * each iteration up to 8192 bytes.
+ */
+ static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b
+ static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k
+
+ /**
+ * Empty {@code ByteString}.
+ */
+ public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
+
+ /**
+ * An interface to efficiently copy {@code byte[]}.
+ *
+ * <p>One of the noticeable costs of copying a byte[] into a new array using
+ * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown
+ * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this
+ * expensive nullification and provide substantial performance gain. Unfortunately this does not
+ * hold on Android runtimes and could make the copy slightly slower due to additional code in
+ * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier
+ * for Hotspot and Android runtimes.
+ */
+ private interface ByteArrayCopier {
+ /**
+ * Copies the specified range of the specified array into a new array
+ */
+ byte[] copyFrom(byte[] bytes, int offset, int size);
+ }
+
+ /** Implementation of {@code ByteArrayCopier} which uses {@link System#arraycopy}. */
+ private static final class SystemByteArrayCopier implements ByteArrayCopier {
+ @Override
+ public byte[] copyFrom(byte[] bytes, int offset, int size) {
+ byte[] copy = new byte[size];
+ System.arraycopy(bytes, offset, copy, 0, size);
+ return copy;
+ }
+ }
+
+ /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfRange}. */
+ private static final class ArraysByteArrayCopier implements ByteArrayCopier {
+ @Override
+ public byte[] copyFrom(byte[] bytes, int offset, int size) {
+ return Arrays.copyOfRange(bytes, offset, offset + size);
+ }
+ }
+
+ private static final ByteArrayCopier byteArrayCopier;
+ static {
+ boolean isAndroid = true;
+ try {
+ Class.forName("android.content.Context");
+ } catch (ClassNotFoundException e) {
+ isAndroid = false;
+ }
+
+ byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
+ }
+
+ /**
+ * Cached hash value. Intentionally accessed via a data race, which
+ * is safe because of the Java Memory Model's "no out-of-thin-air values"
+ * guarantees for ints. A value of 0 implies that the hash has not been set.
+ */
+ private int hash = 0;
+
+ // This constructor is here to prevent subclassing outside of this package,
+ ByteString() {}
+
+ /**
+ * Gets the byte at the given index. This method should be used only for
+ * random access to individual bytes. To access bytes sequentially, use the
+ * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
+ * #substring(int, int)} first if necessary.
+ *
+ * @param index index of byte
+ * @return the value
+ * @throws IndexOutOfBoundsException {@code index < 0 or index >= size}
+ */
+ public abstract byte byteAt(int index);
+
+ /**
+ * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
+ * To avoid auto-boxing, you may get the iterator manually and call
+ * {@link ByteIterator#nextByte()}.
+ *
+ * @return the iterator
+ */
+ @Override
+ public final ByteIterator iterator() {
+ return new ByteIterator() {
+ private int position = 0;
+ private final int limit = size();
+
+ @Override
+ public boolean hasNext() {
+ return position < limit;
+ }
+
+ @Override
+ public Byte next() {
+ // Boxing calls Byte.valueOf(byte), which does not instantiate.
+ return nextByte();
+ }
+
+ @Override
+ public byte nextByte() {
+ try {
+ return byteAt(position++);
+ } catch (IndexOutOfBoundsException e) {
+ throw new NoSuchElementException(e.getMessage());
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * This interface extends {@code Iterator<Byte>}, so that we can return an
+ * unboxed {@code byte}.
+ */
+ public interface ByteIterator extends Iterator<Byte> {
+ /**
+ * An alternative to {@link Iterator#next()} that returns an
+ * unboxed primitive {@code byte}.
+ *
+ * @return the next {@code byte} in the iteration
+ * @throws NoSuchElementException if the iteration has no more elements
+ */
+ byte nextByte();
+ }
+
+ /**
+ * Gets the number of bytes.
+ *
+ * @return size in bytes
+ */
+ public abstract int size();
+
+ /**
+ * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
+ *
+ * @return true if this is zero bytes long
+ */
+ public final boolean isEmpty() {
+ return size() == 0;
+ }
+
+ // =================================================================
+ // ByteString -> substring
+
+ /**
+ * Return the substring from {@code beginIndex}, inclusive, to the end of the
+ * string.
+ *
+ * @param beginIndex start at this index
+ * @return substring sharing underlying data
+ * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
+ * {@code beginIndex > size()}.
+ */
+ public final ByteString substring(int beginIndex) {
+ return substring(beginIndex, size());
+ }
+
+ /**
+ * Return the substring from {@code beginIndex}, inclusive, to {@code
+ * endIndex}, exclusive.
+ *
+ * @param beginIndex start at this index
+ * @param endIndex the last character is the one before this index
+ * @return substring sharing underlying data
+ * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
+ * {@code endIndex > size()}, or {@code beginIndex > endIndex}.
+ */
+ public abstract ByteString substring(int beginIndex, int endIndex);
+
+ /**
+ * Tests if this bytestring starts with the specified prefix.
+ * Similar to {@link String#startsWith(String)}
+ *
+ * @param prefix the prefix.
+ * @return <code>true</code> if the byte sequence represented by the
+ * argument is a prefix of the byte sequence represented by
+ * this string; <code>false</code> otherwise.
+ */
+ public final boolean startsWith(ByteString prefix) {
+ return size() >= prefix.size() &&
+ substring(0, prefix.size()).equals(prefix);
+ }
+
+ /**
+ * Tests if this bytestring ends with the specified suffix.
+ * Similar to {@link String#endsWith(String)}
+ *
+ * @param suffix the suffix.
+ * @return <code>true</code> if the byte sequence represented by the
+ * argument is a suffix of the byte sequence represented by
+ * this string; <code>false</code> otherwise.
+ */
+ public final boolean endsWith(ByteString suffix) {
+ return size() >= suffix.size() &&
+ substring(size() - suffix.size()).equals(suffix);
+ }
+
+ // =================================================================
+ // byte[] -> ByteString
+
+ /**
+ * Copies the given bytes into a {@code ByteString}.
+ *
+ * @param bytes source array
+ * @param offset offset in source array
+ * @param size number of bytes to copy
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFrom(byte[] bytes, int offset, int size) {
+ return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
+ }
+
+ /**
+ * Copies the given bytes into a {@code ByteString}.
+ *
+ * @param bytes to copy
+ * @return new {@code ByteString}
+ */
+ 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.
+ */
+ static ByteString wrap(ByteBuffer buffer) {
+ if (buffer.hasArray()) {
+ final int offset = buffer.arrayOffset();
+ return ByteString.wrap(buffer.array(), offset + buffer.position(), buffer.remaining());
+ } else {
+ return new NioByteString(buffer);
+ }
+ }
+
+ /**
+ * 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
+ * a {@code ByteString}.
+ *
+ * @param bytes source buffer
+ * @param size number of bytes to copy
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFrom(ByteBuffer bytes, int size) {
+ byte[] copy = new byte[size];
+ bytes.get(copy);
+ return new LiteralByteString(copy);
+ }
+
+ /**
+ * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
+ * a {@code ByteString}.
+ *
+ * @param bytes sourceBuffer
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFrom(ByteBuffer bytes) {
+ return copyFrom(bytes, bytes.remaining());
+ }
+
+ /**
+ * Encodes {@code text} into a sequence of bytes using the named charset
+ * and returns the result as a {@code ByteString}.
+ *
+ * @param text source string
+ * @param charsetName encoding to use
+ * @return new {@code ByteString}
+ * @throws UnsupportedEncodingException if the encoding isn't found
+ */
+ public static ByteString copyFrom(String text, String charsetName)
+ throws UnsupportedEncodingException {
+ return new LiteralByteString(text.getBytes(charsetName));
+ }
+
+ /**
+ * Encodes {@code text} into a sequence of bytes using the named charset
+ * and returns the result as a {@code ByteString}.
+ *
+ * @param text source string
+ * @param charset encode using this charset
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFrom(String text, Charset charset) {
+ return new LiteralByteString(text.getBytes(charset));
+ }
+
+ /**
+ * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
+ * result as a {@code ByteString}.
+ *
+ * @param text source string
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFromUtf8(String text) {
+ return new LiteralByteString(text.getBytes(Internal.UTF_8));
+ }
+
+ // =================================================================
+ // InputStream -> ByteString
+
+ /**
+ * Completely reads the given stream's bytes into a
+ * {@code ByteString}, blocking if necessary until all bytes are
+ * read through to the end of the stream.
+ *
+ * <b>Performance notes:</b> The returned {@code ByteString} is an
+ * immutable tree of byte arrays ("chunks") of the stream data. The
+ * first chunk is small, with subsequent chunks each being double
+ * the size, up to 8K.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
+ *
+ * @param streamToDrain The source stream, which is read completely
+ * but not closed.
+ * @return A new {@code ByteString} which is made up of chunks of
+ * various sizes, depending on the behavior of the underlying
+ * stream.
+ * @throws IOException IOException is thrown if there is a problem
+ * reading the underlying stream.
+ */
+ public static ByteString readFrom(InputStream streamToDrain)
+ throws IOException {
+ return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
+ }
+
+ /**
+ * Completely reads the given stream's bytes into a
+ * {@code ByteString}, blocking if necessary until all bytes are
+ * read through to the end of the stream.
+ *
+ * <b>Performance notes:</b> The returned {@code ByteString} is an
+ * immutable tree of byte arrays ("chunks") of the stream data. The
+ * chunkSize parameter sets the size of these byte arrays.
+ *
+ * <p>Each byte read from the input stream will be copied twice to ensure
+ * that the resulting ByteString is truly immutable.
+ *
+ * @param streamToDrain The source stream, which is read completely
+ * but not closed.
+ * @param chunkSize The size of the chunks in which to read the
+ * stream.
+ * @return A new {@code ByteString} which is made up of chunks of
+ * the given size.
+ * @throws IOException IOException is thrown if there is a problem
+ * reading the underlying stream.
+ */
+ public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
+ throws IOException {
+ return readFrom(streamToDrain, chunkSize, chunkSize);
+ }
+
+ // Helper method that takes the chunk size range as a parameter.
+ public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
+ int maxChunkSize) throws IOException {
+ Collection<ByteString> results = new ArrayList<ByteString>();
+
+ // copy the inbound bytes into a list of chunks; the chunk size
+ // grows exponentially to support both short and long streams.
+ int chunkSize = minChunkSize;
+ while (true) {
+ ByteString chunk = readChunk(streamToDrain, chunkSize);
+ if (chunk == null) {
+ break;
+ }
+ results.add(chunk);
+ chunkSize = Math.min(chunkSize * 2, maxChunkSize);
+ }
+
+ return ByteString.copyFrom(results);
+ }
+
+ /**
+ * Blocks until a chunk of the given size can be made from the
+ * stream, or EOF is reached. Calls read() repeatedly in case the
+ * given stream implementation doesn't completely fill the given
+ * buffer in one read() call.
+ *
+ * @return A chunk of the desired size, or else a chunk as large as
+ * was available when end of stream was reached. Returns null if the
+ * given stream had no more data in it.
+ */
+ private static ByteString readChunk(InputStream in, final int chunkSize)
+ throws IOException {
+ final byte[] buf = new byte[chunkSize];
+ int bytesRead = 0;
+ while (bytesRead < chunkSize) {
+ final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
+ if (count == -1) {
+ break;
+ }
+ bytesRead += count;
+ }
+
+ if (bytesRead == 0) {
+ return null;
+ }
+
+ // Always make a copy since InputStream could steal a reference to buf.
+ return ByteString.copyFrom(buf, 0, bytesRead);
+ }
+
+ // =================================================================
+ // Multiple ByteStrings -> One ByteString
+
+ /**
+ * Concatenate the given {@code ByteString} to this one. Short concatenations,
+ * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
+ * produced by copying the underlying bytes (as per Rope.java, <a
+ * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a>. In general, the concatenate involves no copying.
+ *
+ * @param other string to concatenate
+ * @return a new {@code ByteString} instance
+ */
+ public final ByteString concat(ByteString other) {
+ if (Integer.MAX_VALUE - size() < other.size()) {
+ throw new IllegalArgumentException("ByteString would be too long: " +
+ size() + "+" + other.size());
+ }
+
+ return RopeByteString.concatenate(this, other);
+ }
+
+ /**
+ * Concatenates all byte strings in the iterable and returns the result.
+ * This is designed to run in O(list size), not O(total bytes).
+ *
+ * <p>The returned {@code ByteString} is not necessarily a unique object.
+ * If the list is empty, the returned object is the singleton empty
+ * {@code ByteString}. If the list has only one element, that
+ * {@code ByteString} will be returned without copying.
+ *
+ * @param byteStrings strings to be concatenated
+ * @return new {@code ByteString}
+ */
+ public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
+ // Determine the size;
+ final int size;
+ if (!(byteStrings instanceof Collection)) {
+ int tempSize = 0;
+ for (Iterator<ByteString> iter = byteStrings.iterator(); iter.hasNext();
+ iter.next(), ++tempSize) {
+ }
+ size = tempSize;
+ } else {
+ size = ((Collection<ByteString>) byteStrings).size();
+ }
+
+ if (size == 0) {
+ return EMPTY;
+ }
+
+ return balancedConcat(byteStrings.iterator(), size);
+ }
+
+ // Internal function used by copyFrom(Iterable<ByteString>).
+ // Create a balanced concatenation of the next "length" elements from the
+ // iterable.
+ private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
+ if (length < 1) {
+ throw new IllegalArgumentException(String.format("length (%s) must be >= 1", length));
+ }
+ ByteString result;
+ if (length == 1) {
+ result = iterator.next();
+ } else {
+ int halfLength = length >>> 1;
+ ByteString left = balancedConcat(iterator, halfLength);
+ ByteString right = balancedConcat(iterator, length - halfLength);
+ result = left.concat(right);
+ }
+ return result;
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ /**
+ * Copies bytes into a buffer at the given offset.
+ *
+ * @param target buffer to copy into
+ * @param offset in the target buffer
+ * @throws IndexOutOfBoundsException if the offset is negative or too large
+ */
+ public void copyTo(byte[] target, int offset) {
+ copyTo(target, 0, offset, size());
+ }
+
+ /**
+ * Copies bytes into a buffer.
+ *
+ * @param target buffer to copy into
+ * @param sourceOffset offset within these bytes
+ * @param targetOffset offset within the target buffer
+ * @param numberToCopy number of bytes to copy
+ * @throws IndexOutOfBoundsException if an offset or size is negative or too
+ * large
+ */
+ public final void copyTo(byte[] target, int sourceOffset, int targetOffset,
+ int numberToCopy) {
+ checkRange(sourceOffset, sourceOffset + numberToCopy, size());
+ checkRange(targetOffset, targetOffset + numberToCopy, target.length);
+ if (numberToCopy > 0) {
+ copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+ }
+ }
+
+ /**
+ * Internal (package private) implementation of
+ * {@link #copyTo(byte[],int,int,int)}.
+ * It assumes that all error checking has already been performed and that
+ * {@code numberToCopy > 0}.
+ */
+ protected abstract void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy);
+
+ /**
+ * Copies bytes into a ByteBuffer.
+ *
+ * @param target ByteBuffer to copy into.
+ * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
+ * @throws java.nio.BufferOverflowException if the {@code target}'s
+ * remaining() space is not large enough to hold the data.
+ */
+ public abstract void copyTo(ByteBuffer target);
+
+ /**
+ * Copies bytes to a {@code byte[]}.
+ *
+ * @return copied bytes
+ */
+ public final byte[] toByteArray() {
+ final int size = size();
+ if (size == 0) {
+ return Internal.EMPTY_BYTE_ARRAY;
+ }
+ byte[] result = new byte[size];
+ copyToInternal(result, 0, 0, size);
+ return result;
+ }
+
+ /**
+ * Writes a copy of the contents of this byte string to the specified output stream argument.
+ *
+ * @param out the output stream to which to write the data.
+ * @throws IOException if an I/O error occurs.
+ */
+ public abstract void writeTo(OutputStream out) throws IOException;
+
+ /**
+ * Writes a specified part of this byte string to an output stream.
+ *
+ * @param out the output stream to which to write the data.
+ * @param sourceOffset offset within these bytes
+ * @param numberToWrite number of bytes to write
+ * @throws IOException if an I/O error occurs.
+ * @throws IndexOutOfBoundsException if an offset or size is negative or too large
+ */
+ final void writeTo(OutputStream out, int sourceOffset, int numberToWrite)
+ throws IOException {
+ checkRange(sourceOffset, sourceOffset + numberToWrite, size());
+ if (numberToWrite > 0) {
+ writeToInternal(out, sourceOffset, numberToWrite);
+ }
+ }
+
+ /**
+ * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes
+ * all error checking has already been done.
+ */
+ abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)
+ throws IOException;
+
+ /**
+ * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling
+ * this method may result in multiple operations on the target {@link ByteOutput}.
+ *
+ * <p>This method may expose internal backing buffers of the {@link ByteString} to the {@link
+ * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
+ * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
+ *
+ * @param byteOutput the output target to receive the bytes
+ * @throws IOException if an I/O error occurs
+ * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput)
+ */
+ abstract void writeTo(ByteOutput byteOutput) throws IOException;
+
+
+ /**
+ * Constructs a read-only {@code java.nio.ByteBuffer} whose content
+ * is equal to the contents of this byte string.
+ * The result uses the same backing array as the byte string, if possible.
+ *
+ * @return wrapped bytes
+ */
+ public abstract ByteBuffer asReadOnlyByteBuffer();
+
+ /**
+ * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
+ * such that the concatenation of their contents is equal to the contents
+ * of this byte string. The result uses the same backing arrays as the
+ * byte string.
+ * <p>
+ * By returning a list, implementations of this method may be able to avoid
+ * copying even when there are multiple backing arrays.
+ *
+ * @return a list of wrapped bytes
+ */
+ public abstract List<ByteBuffer> asReadOnlyByteBufferList();
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes using the
+ * specified charset.
+ *
+ * @param charsetName encode using this charset
+ * @return new string
+ * @throws UnsupportedEncodingException if charset isn't recognized
+ */
+ public final String toString(String charsetName)
+ throws UnsupportedEncodingException {
+ try {
+ return toString(Charset.forName(charsetName));
+ } catch (UnsupportedCharsetException e) {
+ UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName);
+ exception.initCause(e);
+ throw exception;
+ }
+ }
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes using the
+ * specified charset. Returns the same empty String if empty.
+ *
+ * @param charset encode using this charset
+ * @return new string
+ */
+ public final String toString(Charset charset) {
+ return size() == 0 ? "" : toStringInternal(charset);
+ }
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes using the
+ * specified charset.
+ *
+ * @param charset encode using this charset
+ * @return new string
+ */
+ protected abstract String toStringInternal(Charset charset);
+
+ // =================================================================
+ // UTF-8 decoding
+
+ /**
+ * Constructs a new {@code String} by decoding the bytes as UTF-8.
+ *
+ * @return new string using UTF-8 encoding
+ */
+ public final String toStringUtf8() {
+ return toString(Internal.UTF_8);
+ }
+
+ /**
+ * Tells whether this {@code ByteString} represents a well-formed UTF-8
+ * byte sequence, such that the original bytes can be converted to a
+ * String object and then round tripped back to bytes without loss.
+ *
+ * <p>More precisely, returns {@code true} whenever: <pre> {@code
+ * Arrays.equals(byteString.toByteArray(),
+ * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>This method returns {@code false} for "overlong" byte sequences,
+ * as well as for 3-byte sequences that would map to a surrogate
+ * character, in accordance with the restricted definition of UTF-8
+ * introduced in Unicode 3.1. Note that the UTF-8 decoder included in
+ * Oracle's JDK has been modified to also reject "overlong" byte
+ * sequences, but (as of 2011) still accepts 3-byte surrogate
+ * character byte sequences.
+ *
+ * <p>See the Unicode Standard,<br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * @return whether the bytes in this {@code ByteString} are a
+ * well-formed UTF-8 byte sequence
+ */
+ public abstract boolean isValidUtf8();
+
+ /**
+ * Tells whether the given byte sequence is a well-formed, malformed, or
+ * incomplete UTF-8 byte sequence. This method accepts and returns a partial
+ * state result, allowing the bytes for a complete UTF-8 byte sequence to be
+ * composed from multiple {@code ByteString} segments.
+ *
+ * @param state either {@code 0} (if this is the initial decoding operation)
+ * or the value returned from a call to a partial decoding method for the
+ * previous bytes
+ * @param offset offset of the first byte to check
+ * @param length number of bytes to check
+ *
+ * @return {@code -1} if the partial byte sequence is definitely malformed,
+ * {@code 0} if it is well-formed (no additional input needed), or, if the
+ * byte sequence is "incomplete", i.e. apparently terminated in the middle of
+ * a character, an opaque integer "state" value containing enough information
+ * to decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ protected abstract int partialIsValidUtf8(int state, int offset, int length);
+
+ // =================================================================
+ // equals() and hashCode()
+
+ @Override
+ public abstract boolean equals(Object o);
+
+ /**
+ * Base class for leaf {@link ByteString}s (i.e. non-ropes).
+ */
+ abstract static class LeafByteString extends ByteString {
+ @Override
+ protected final int getTreeDepth() {
+ return 0;
+ }
+
+ @Override
+ protected final boolean isBalanced() {
+ return true;
+ }
+
+
+ /**
+ * Check equality of the substring of given length of this object starting at
+ * zero with another {@code ByteString} 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.
+ */
+ abstract boolean equalsRange(ByteString other, int offset, int length);
+ }
+
+ /**
+ * Compute the hashCode using the traditional algorithm from {@link
+ * ByteString}.
+ *
+ * @return hashCode value
+ */
+ @Override
+ public final int hashCode() {
+ int h = hash;
+
+ if (h == 0) {
+ int size = size();
+ h = partialHash(size, 0, size);
+ if (h == 0) {
+ h = 1;
+ }
+ hash = h;
+ }
+ return h;
+ }
+
+ // =================================================================
+ // Input stream
+
+ /**
+ * Creates an {@code InputStream} which can be used to read the bytes.
+ * <p>
+ * The {@link InputStream} returned by this method is guaranteed to be
+ * completely non-blocking. The method {@link InputStream#available()}
+ * returns the number of bytes remaining in the stream. The methods
+ * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
+ * and {@link InputStream#skip(long)} will read/skip as many bytes as are
+ * available. The method {@link InputStream#markSupported()} returns
+ * {@code true}.
+ * <p>
+ * The methods in the returned {@link InputStream} might <b>not</b> be
+ * thread safe.
+ *
+ * @return an input stream that returns the bytes of this byte string.
+ */
+ public abstract InputStream newInput();
+
+ /**
+ * Creates a {@link CodedInputStream} which can be used to read the bytes.
+ * Using this is often more efficient than creating a {@link CodedInputStream}
+ * that wraps the result of {@link #newInput()}.
+ *
+ * @return stream based on wrapped data
+ */
+ public abstract CodedInputStream newCodedInput();
+
+ // =================================================================
+ // Output stream
+
+ /**
+ * Creates a new {@link Output} with the given initial capacity. Call {@link
+ * Output#toByteString()} to create the {@code ByteString} instance.
+ * <p>
+ * A {@link ByteString.Output} offers the same functionality as a
+ * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+ * rather than a {@code byte} array.
+ *
+ * @param initialCapacity estimate of number of bytes to be written
+ * @return {@code OutputStream} for building a {@code ByteString}
+ */
+ public static Output newOutput(int initialCapacity) {
+ return new Output(initialCapacity);
+ }
+
+ /**
+ * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
+ * the {@code ByteString} instance.
+ * <p>
+ * A {@link ByteString.Output} offers the same functionality as a
+ * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
+ * rather than a {@code byte array}.
+ *
+ * @return {@code OutputStream} for building a {@code ByteString}
+ */
+ public static Output newOutput() {
+ return new Output(CONCATENATE_BY_COPY_SIZE);
+ }
+
+ /**
+ * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
+ * create the {@code ByteString} instance.
+ */
+ public static final class Output extends OutputStream {
+ // Implementation note.
+ // The public methods of this class must be synchronized. ByteStrings
+ // are guaranteed to be immutable. Without some sort of locking, it could
+ // be possible for one thread to call toByteSring(), while another thread
+ // is still modifying the underlying byte array.
+
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+ // argument passed by user, indicating initial capacity.
+ private final int initialCapacity;
+ // ByteStrings to be concatenated to create the result
+ private final ArrayList<ByteString> flushedBuffers;
+ // Total number of bytes in the ByteStrings of flushedBuffers
+ private int flushedBuffersTotalBytes;
+ // Current buffer to which we are writing
+ private byte[] buffer;
+ // Location in buffer[] to which we write the next byte.
+ private int bufferPos;
+
+ /**
+ * Creates a new ByteString output stream with the specified
+ * initial capacity.
+ *
+ * @param initialCapacity the initial capacity of the output stream.
+ */
+ Output(int initialCapacity) {
+ if (initialCapacity < 0) {
+ throw new IllegalArgumentException("Buffer size < 0");
+ }
+ this.initialCapacity = initialCapacity;
+ this.flushedBuffers = new ArrayList<ByteString>();
+ this.buffer = new byte[initialCapacity];
+ }
+
+ @Override
+ public synchronized void write(int b) {
+ if (bufferPos == buffer.length) {
+ flushFullBuffer(1);
+ }
+ buffer[bufferPos++] = (byte)b;
+ }
+
+ @Override
+ public synchronized void write(byte[] b, int offset, int length) {
+ if (length <= buffer.length - bufferPos) {
+ // The bytes can fit into the current buffer.
+ System.arraycopy(b, offset, buffer, bufferPos, length);
+ bufferPos += length;
+ } else {
+ // Use up the current buffer
+ int copySize = buffer.length - bufferPos;
+ System.arraycopy(b, offset, buffer, bufferPos, copySize);
+ offset += copySize;
+ length -= copySize;
+ // Flush the buffer, and get a new buffer at least big enough to cover
+ // what we still need to output
+ flushFullBuffer(length);
+ System.arraycopy(b, offset, buffer, 0 /* count */, length);
+ bufferPos = length;
+ }
+ }
+
+ /**
+ * Creates a byte string. Its size is the current size of this output
+ * stream and its output has been copied to it.
+ *
+ * @return the current contents of this output stream, as a byte string.
+ */
+ public synchronized ByteString toByteString() {
+ flushLastBuffer();
+ return ByteString.copyFrom(flushedBuffers);
+ }
+
+ /**
+ * Implement java.util.Arrays.copyOf() for jdk 1.5.
+ */
+ private byte[] copyArray(byte[] buffer, int length) {
+ byte[] result = new byte[length];
+ System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
+ return result;
+ }
+
+ /**
+ * Writes the complete contents of this byte array output stream to
+ * the specified output stream argument.
+ *
+ * @param out the output stream to which to write the data.
+ * @throws IOException if an I/O error occurs.
+ */
+ public void writeTo(OutputStream out) throws IOException {
+ ByteString[] cachedFlushBuffers;
+ byte[] cachedBuffer;
+ int cachedBufferPos;
+ synchronized (this) {
+ // Copy the information we need into local variables so as to hold
+ // the lock for as short a time as possible.
+ cachedFlushBuffers =
+ flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
+ cachedBuffer = buffer;
+ cachedBufferPos = bufferPos;
+ }
+ for (ByteString byteString : cachedFlushBuffers) {
+ byteString.writeTo(out);
+ }
+
+ out.write(copyArray(cachedBuffer, cachedBufferPos));
+ }
+
+ /**
+ * Returns the current size of the output stream.
+ *
+ * @return the current size of the output stream
+ */
+ public synchronized int size() {
+ return flushedBuffersTotalBytes + bufferPos;
+ }
+
+ /**
+ * Resets this stream, so that all currently accumulated output in the
+ * output stream is discarded. The output stream can be used again,
+ * reusing the already allocated buffer space.
+ */
+ public synchronized void reset() {
+ flushedBuffers.clear();
+ flushedBuffersTotalBytes = 0;
+ bufferPos = 0;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("<ByteString.Output@%s size=%d>",
+ Integer.toHexString(System.identityHashCode(this)), size());
+ }
+
+ /**
+ * Internal function used by writers. The current buffer is full, and the
+ * writer needs a new buffer whose size is at least the specified minimum
+ * size.
+ */
+ private void flushFullBuffer(int minSize) {
+ flushedBuffers.add(new LiteralByteString(buffer));
+ flushedBuffersTotalBytes += buffer.length;
+ // We want to increase our total capacity by 50%, but as a minimum,
+ // the new buffer should also at least be >= minSize and
+ // >= initial Capacity.
+ int newSize = Math.max(initialCapacity,
+ Math.max(minSize, flushedBuffersTotalBytes >>> 1));
+ buffer = new byte[newSize];
+ bufferPos = 0;
+ }
+
+ /**
+ * Internal function used by {@link #toByteString()}. The current buffer may
+ * or may not be full, but it needs to be flushed.
+ */
+ private void flushLastBuffer() {
+ if (bufferPos < buffer.length) {
+ if (bufferPos > 0) {
+ byte[] bufferCopy = copyArray(buffer, bufferPos);
+ flushedBuffers.add(new LiteralByteString(bufferCopy));
+ }
+ // We reuse this buffer for further writes.
+ } else {
+ // Buffer is completely full. Huzzah.
+ flushedBuffers.add(new LiteralByteString(buffer));
+ // 99% of the time, we're not going to use this OutputStream again.
+ // We set buffer to an empty byte stream so that we're handling this
+ // case without wasting space. In the rare case that more writes
+ // *do* occur, this empty buffer will be flushed and an appropriately
+ // sized new buffer will be created.
+ buffer = EMPTY_BYTE_ARRAY;
+ }
+ flushedBuffersTotalBytes += bufferPos;
+ bufferPos = 0;
+ }
+ }
+
+ /**
+ * Constructs a new {@code ByteString} builder, which allows you to
+ * efficiently construct a {@code ByteString} by writing to a {@link
+ * CodedOutputStream}. Using this is much more efficient than calling {@code
+ * newOutput()} and wrapping that in a {@code CodedOutputStream}.
+ *
+ * <p>This is package-private because it's a somewhat confusing interface.
+ * Users can call {@link Message#toByteString()} instead of calling this
+ * directly.
+ *
+ * @param size The target byte size of the {@code ByteString}. You must write
+ * exactly this many bytes before building the result.
+ * @return the builder
+ */
+ static CodedBuilder newCodedBuilder(int size) {
+ return new CodedBuilder(size);
+ }
+
+ /** See {@link ByteString#newCodedBuilder(int)}. */
+ static final class CodedBuilder {
+ private final CodedOutputStream output;
+ private final byte[] buffer;
+
+ private CodedBuilder(int size) {
+ buffer = new byte[size];
+ output = CodedOutputStream.newInstance(buffer);
+ }
+
+ public ByteString build() {
+ output.checkNoSpaceLeft();
+
+ // We can be confident that the CodedOutputStream will not modify the
+ // underlying bytes anymore because it already wrote all of them. So,
+ // no need to make a copy.
+ return new LiteralByteString(buffer);
+ }
+
+ public CodedOutputStream getCodedOutput() {
+ return output;
+ }
+ }
+
+ // =================================================================
+ // Methods {@link RopeByteString} needs on instances, which aren't part of the
+ // public API.
+
+ /**
+ * Return the depth of the tree representing this {@code ByteString}, if any,
+ * whose root is this node. If this is a leaf node, return 0.
+ *
+ * @return tree depth or zero
+ */
+ protected abstract int getTreeDepth();
+
+ /**
+ * Return {@code true} if this ByteString is literal (a leaf node) or a
+ * flat-enough tree in the sense of {@link RopeByteString}.
+ *
+ * @return true if the tree is flat enough
+ */
+ protected abstract boolean isBalanced();
+
+ /**
+ * Return the cached hash code if available.
+ *
+ * @return value of cached hash code or 0 if not computed yet
+ */
+ protected final int peekCachedHashCode() {
+ return hash;
+ }
+
+ /**
+ * Compute the hash across the value bytes starting with the given hash, and
+ * return the result. This is used to compute the hash across strings
+ * represented as a set of pieces by allowing the hash computation to be
+ * continued from piece to piece.
+ *
+ * @param h starting hash value
+ * @param offset offset into this value to start looking at data values
+ * @param length number of data values to include in the hash computation
+ * @return ending hash value
+ */
+ protected abstract int partialHash(int h, int offset, int length);
+
+ /**
+ * Checks that the given index falls within the specified array size.
+ *
+ * @param index the index position to be tested
+ * @param size the length of the array
+ * @throws IndexOutOfBoundsException if the index does not fall within the array.
+ */
+ static void checkIndex(int index, int size) {
+ if ((index | (size - (index + 1))) < 0) {
+ if (index < 0) {
+ throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
+ }
+ throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size);
+ }
+ }
+
+ /**
+ * Checks that the given range falls within the bounds of an array
+ *
+ * @param startIndex the start index of the range (inclusive)
+ * @param endIndex the end index of the range (exclusive)
+ * @param size the size of the array.
+ * @return the length of the range.
+ * @throws IndexOutOfBoundsException some or all of the range falls outside of the array.
+ */
+ static int checkRange(int startIndex, int endIndex, int size) {
+ final int length = endIndex - startIndex;
+ if ((startIndex | endIndex | length | (size - endIndex)) < 0) {
+ if (startIndex < 0) {
+ throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0");
+ }
+ if (endIndex < startIndex) {
+ throw new IndexOutOfBoundsException(
+ "Beginning index larger than ending index: " + startIndex + ", " + endIndex);
+ }
+ // endIndex >= size
+ throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size);
+ }
+ return length;
+ }
+
+ @Override
+ public final String toString() {
+ 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
+ final void writeTo(ByteOutput output) throws IOException {
+ output.writeLazy(bytes, getOffsetIntoBytes(), size());
+ }
+
+ @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/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
new file mode 100644
index 0000000000..239798e440
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -0,0 +1,2896 @@
+// 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 static com.google.protobuf.Internal.EMPTY_BYTE_ARRAY;
+import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
+import static com.google.protobuf.Internal.UTF_8;
+import static com.google.protobuf.Internal.checkNotNull;
+import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
+import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Reads and decodes protocol message fields.
+ *
+ * <p>This class contains two kinds of methods: methods that read specific protocol message
+ * constructs and field types (e.g. {@link #readTag()} and {@link #readInt32()}) and methods that
+ * read low-level values (e.g. {@link #readRawVarint32()} and {@link #readRawBytes}). If you are
+ * reading encoded protocol messages, you should use the former methods, but if you are reading some
+ * other format of your own design, use the latter.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class CodedInputStream {
+ private static final int DEFAULT_BUFFER_SIZE = 4096;
+ private static final int DEFAULT_RECURSION_LIMIT = 100;
+ // Integer.MAX_VALUE == 0x7FFFFFF == INT_MAX from limits.h
+ private static final int DEFAULT_SIZE_LIMIT = Integer.MAX_VALUE;
+
+ /** Visible for subclasses. See setRecursionLimit() */
+ int recursionDepth;
+
+ int recursionLimit = DEFAULT_RECURSION_LIMIT;
+
+ /** Visible for subclasses. See setSizeLimit() */
+ int sizeLimit = DEFAULT_SIZE_LIMIT;
+
+ /** Create a new CodedInputStream wrapping the given InputStream. */
+ public static CodedInputStream newInstance(final InputStream input) {
+ return newInstance(input, DEFAULT_BUFFER_SIZE);
+ }
+
+ /** Create a new CodedInputStream wrapping the given InputStream. */
+ static CodedInputStream newInstance(final InputStream input, int bufferSize) {
+ if (input == null) {
+ // TODO(nathanmittler): Ideally we should throw here. This is done for backward compatibility.
+ return newInstance(EMPTY_BYTE_ARRAY);
+ }
+ return new StreamDecoder(input, bufferSize);
+ }
+
+ /** Create a new CodedInputStream wrapping the given byte array. */
+ public static CodedInputStream newInstance(final byte[] buf) {
+ return newInstance(buf, 0, buf.length);
+ }
+
+ /** Create a new CodedInputStream wrapping the given byte array slice. */
+ public static CodedInputStream newInstance(final byte[] buf, final int off, final int len) {
+ return newInstance(buf, off, len, false /* bufferIsImmutable */);
+ }
+
+ /** Create a new CodedInputStream wrapping the given byte array slice. */
+ static CodedInputStream newInstance(
+ final byte[] buf, final int off, final int len, final boolean bufferIsImmutable) {
+ ArrayDecoder result = new ArrayDecoder(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
+ // 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(len);
+ } 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;
+ }
+
+ /**
+ * Create a new CodedInputStream wrapping the given ByteBuffer. The data starting from the
+ * ByteBuffer's current position to its limit will be read. The returned CodedInputStream may or
+ * may not share the underlying data in the ByteBuffer, therefore the ByteBuffer cannot be changed
+ * while the CodedInputStream is in use. Note that the ByteBuffer's position won't be changed by
+ * this function. Concurrent calls with the same ByteBuffer object are safe if no other thread is
+ * trying to alter the ByteBuffer's status.
+ */
+ public static CodedInputStream newInstance(ByteBuffer buf) {
+ return newInstance(buf, false /* bufferIsImmutable */);
+ }
+
+ /** Create a new CodedInputStream wrapping the given buffer. */
+ static CodedInputStream newInstance(ByteBuffer buf, boolean bufferIsImmutable) {
+ if (buf.hasArray()) {
+ return newInstance(
+ buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), bufferIsImmutable);
+ }
+
+ if (buf.isDirect() && UnsafeDirectNioDecoder.isSupported()) {
+ return new UnsafeDirectNioDecoder(buf, bufferIsImmutable);
+ }
+
+ // The buffer is non-direct and does not expose the underlying array. Using the ByteBuffer API
+ // to access individual bytes is very slow, so just copy the buffer to an array.
+ // TODO(nathanmittler): Re-evaluate with Java 9
+ byte[] buffer = new byte[buf.remaining()];
+ buf.duplicate().get(buffer);
+ return newInstance(buffer, 0, buffer.length, true);
+ }
+
+ /** Disable construction/inheritance outside of this class. */
+ private CodedInputStream() {}
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Attempt to read a field tag, returning zero if we have reached EOF. Protocol message parsers
+ * use this to read tags, since a protocol message may legally end wherever a tag occurs, and zero
+ * is not a valid tag number.
+ */
+ public abstract int readTag() throws IOException;
+
+ /**
+ * Verifies that the last call to readTag() returned the given tag value. This is used to verify
+ * that a nested group ended with the correct end tag.
+ *
+ * @throws InvalidProtocolBufferException {@code value} does not match the last tag.
+ */
+ public abstract void checkLastTagWas(final int value) throws InvalidProtocolBufferException;
+
+ public abstract int getLastTag();
+
+ /**
+ * Reads and discards a single field, given its tag value.
+ *
+ * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
+ * Otherwise, returns {@code true}.
+ */
+ public abstract boolean skipField(final int tag) throws IOException;
+
+ /**
+ * Reads a single field and writes it to output in wire format, given its tag value.
+ *
+ * @return {@code false} if the tag is an endgroup tag, in which case nothing is skipped.
+ * Otherwise, returns {@code true}.
+ * @deprecated use {@code UnknownFieldSet} or {@code UnknownFieldSetLite} to skip to an output
+ * stream.
+ */
+ @Deprecated
+ public abstract boolean skipField(final int tag, final CodedOutputStream output)
+ throws IOException;
+
+ /**
+ * Reads and discards an entire message. This will read either until EOF or until an endgroup tag,
+ * whichever comes first.
+ */
+ public abstract void skipMessage() throws IOException;
+
+ /**
+ * Reads an entire message and writes it to output in wire format. This will read either until EOF
+ * or until an endgroup tag, whichever comes first.
+ */
+ public abstract void skipMessage(CodedOutputStream output) throws IOException;
+
+
+ // -----------------------------------------------------------------
+
+ /** Read a {@code double} field value from the stream. */
+ public abstract double readDouble() throws IOException;
+
+ /** Read a {@code float} field value from the stream. */
+ public abstract float readFloat() throws IOException;
+
+ /** Read a {@code uint64} field value from the stream. */
+ public abstract long readUInt64() throws IOException;
+
+ /** Read an {@code int64} field value from the stream. */
+ public abstract long readInt64() throws IOException;
+
+ /** Read an {@code int32} field value from the stream. */
+ public abstract int readInt32() throws IOException;
+
+ /** Read a {@code fixed64} field value from the stream. */
+ public abstract long readFixed64() throws IOException;
+
+ /** Read a {@code fixed32} field value from the stream. */
+ public abstract int readFixed32() throws IOException;
+
+ /** Read a {@code bool} field value from the stream. */
+ public abstract boolean readBool() throws IOException;
+
+ /**
+ * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
+ * replace the offending bytes with the standard UTF-8 replacement character.
+ */
+ public abstract String readString() throws IOException;
+
+ /**
+ * Read a {@code string} field value from the stream. If the stream contains malformed UTF-8,
+ * throw exception {@link InvalidProtocolBufferException}.
+ */
+ public abstract String readStringRequireUtf8() throws IOException;
+
+ /** Read a {@code group} field value from the stream. */
+ public abstract void readGroup(
+ final int fieldNumber,
+ final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+
+ /** Read a {@code group} field value from the stream. */
+ public abstract <T extends MessageLite> T readGroup(
+ final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Reads a {@code group} field value from the stream and merges it into the given {@link
+ * UnknownFieldSet}.
+ *
+ * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so you can just call
+ * {@link #readGroup}.
+ */
+ @Deprecated
+ public abstract void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
+ throws IOException;
+
+ /** Read an embedded message field value from the stream. */
+ public abstract void readMessage(
+ final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+
+ /** Read an embedded message field value from the stream. */
+ public abstract <T extends MessageLite> T readMessage(
+ final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException;
+
+ /** Read a {@code bytes} field value from the stream. */
+ public abstract ByteString readBytes() throws IOException;
+
+ /** Read a {@code bytes} field value from the stream. */
+ public abstract byte[] readByteArray() throws IOException;
+
+ /** Read a {@code bytes} field value from the stream. */
+ public abstract ByteBuffer readByteBuffer() throws IOException;
+
+ /** Read a {@code uint32} field value from the stream. */
+ public abstract int readUInt32() throws IOException;
+
+ /**
+ * Read an enum field value from the stream. Caller is responsible for converting the numeric
+ * value to an actual enum.
+ */
+ public abstract int readEnum() throws IOException;
+
+ /** Read an {@code sfixed32} field value from the stream. */
+ public abstract int readSFixed32() throws IOException;
+
+ /** Read an {@code sfixed64} field value from the stream. */
+ public abstract long readSFixed64() throws IOException;
+
+ /** Read an {@code sint32} field value from the stream. */
+ public abstract int readSInt32() throws IOException;
+
+ /** Read an {@code sint64} field value from the stream. */
+ public abstract long readSInt64() throws IOException;
+
+ // =================================================================
+
+ /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
+ public abstract int readRawVarint32() throws IOException;
+
+ /** Read a raw Varint from the stream. */
+ public abstract long readRawVarint64() throws IOException;
+
+ /** Variant of readRawVarint64 for when uncomfortably close to the limit. */
+ /* Visible for testing */
+ abstract long readRawVarint64SlowPath() throws IOException;
+
+ /** Read a 32-bit little-endian integer from the stream. */
+ public abstract int readRawLittleEndian32() throws IOException;
+
+ /** Read a 64-bit little-endian integer from the stream. */
+ public abstract long readRawLittleEndian64() throws IOException;
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Enables {@link ByteString} aliasing of the underlying buffer, trading off on buffer pinning for
+ * data copies. Only valid for buffer-backed streams.
+ */
+ public abstract void enableAliasing(boolean enabled);
+
+ /**
+ * Set the maximum message recursion depth. In order to prevent malicious messages from causing
+ * stack overflows, {@code CodedInputStream} limits how deeply messages may be nested. The default
+ * limit is 64.
+ *
+ * @return the old limit.
+ */
+ public final int setRecursionLimit(final int limit) {
+ if (limit < 0) {
+ throw new IllegalArgumentException("Recursion limit cannot be negative: " + limit);
+ }
+ final int oldLimit = recursionLimit;
+ recursionLimit = limit;
+ return oldLimit;
+ }
+
+ /**
+ * Only valid for {@link InputStream}-backed streams.
+ *
+ * <p>Set the maximum message size. In order to prevent malicious messages from exhausting memory
+ * or causing integer overflows, {@code CodedInputStream} limits how large a message may be. The
+ * default limit is {@code Integer.MAX_INT}. You should set this limit as small as you can without
+ * harming your app's functionality. Note that size limits only apply when reading from an
+ * {@code InputStream}, not when constructed around a raw byte array.
+ *
+ * <p>If you want to read several messages from a single CodedInputStream, you could call {@link
+ * #resetSizeCounter()} after each one to avoid hitting the size limit.
+ *
+ * @return the old limit.
+ */
+ public final int setSizeLimit(final int limit) {
+ if (limit < 0) {
+ throw new IllegalArgumentException("Size limit cannot be negative: " + limit);
+ }
+ final int oldLimit = sizeLimit;
+ sizeLimit = limit;
+ return oldLimit;
+ }
+
+ /**
+ * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link
+ * InputStream}-backed streams.
+ */
+ public abstract void resetSizeCounter();
+
+ /**
+ * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This is called when
+ * descending into a length-delimited embedded message.
+ *
+ * <p>Note that {@code pushLimit()} does NOT affect how many bytes the {@code CodedInputStream}
+ * reads from an underlying {@code InputStream} when refreshing its buffer. If you need to prevent
+ * reading past a certain point in the underlying {@code InputStream} (e.g. because you expect it
+ * to contain more data after the end of the message which you need to handle differently) then
+ * you must place a wrapper around your {@code InputStream} which limits the amount of data that
+ * can be read from it.
+ *
+ * @return the old limit.
+ */
+ public abstract int pushLimit(int byteLimit) throws InvalidProtocolBufferException;
+
+ /**
+ * Discards the current limit, returning to the previous limit.
+ *
+ * @param oldLimit The old limit, as returned by {@code pushLimit}.
+ */
+ public abstract void popLimit(final int oldLimit);
+
+ /**
+ * Returns the number of bytes to be read before the current limit. If no limit is set, returns
+ * -1.
+ */
+ public abstract int getBytesUntilLimit();
+
+ /**
+ * Returns true if the stream has reached the end of the input. This is the case if either the end
+ * of the underlying input source has been reached or if the stream has reached a limit created
+ * using {@link #pushLimit(int)}.
+ */
+ public abstract boolean isAtEnd() throws IOException;
+
+ /**
+ * The total bytes read up to the current position. Calling {@link #resetSizeCounter()} resets
+ * this value to zero.
+ */
+ public abstract int getTotalBytesRead();
+
+ /**
+ * Read one byte from the input.
+ *
+ * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
+ */
+ public abstract byte readRawByte() throws IOException;
+
+ /**
+ * Read a fixed size of bytes from the input.
+ *
+ * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
+ */
+ public abstract byte[] readRawBytes(final int size) throws IOException;
+
+ /**
+ * Reads and discards {@code size} bytes.
+ *
+ * @throws InvalidProtocolBufferException The end of the stream or the current limit was reached.
+ */
+ public abstract void skipRawBytes(final int size) throws IOException;
+
+ /**
+ * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers into values that can be
+ * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
+ * to be varint encoded, thus always taking 10 bytes on the wire.)
+ *
+ * @param n An unsigned 32-bit integer, stored in a signed int because Java has no explicit
+ * unsigned support.
+ * @return A signed 32-bit integer.
+ */
+ public static int decodeZigZag32(final int n) {
+ return (n >>> 1) ^ -(n & 1);
+ }
+
+ /**
+ * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers into values that can be
+ * efficiently encoded with varint. (Otherwise, negative values must be sign-extended to 64 bits
+ * to be varint encoded, thus always taking 10 bytes on the wire.)
+ *
+ * @param n An unsigned 64-bit integer, stored in a signed int because Java has no explicit
+ * unsigned support.
+ * @return A signed 64-bit integer.
+ */
+ public static long decodeZigZag64(final long n) {
+ return (n >>> 1) ^ -(n & 1);
+ }
+
+ /**
+ * Like {@link #readRawVarint32(InputStream)}, but expects that the caller has already read one
+ * byte. This allows the caller to determine if EOF has been reached before attempting to read.
+ */
+ public static int readRawVarint32(final int firstByte, final InputStream input)
+ throws IOException {
+ if ((firstByte & 0x80) == 0) {
+ return firstByte;
+ }
+
+ int result = firstByte & 0x7f;
+ int offset = 7;
+ for (; offset < 32; offset += 7) {
+ final int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ result |= (b & 0x7f) << offset;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ // Keep reading up to 64 bits.
+ for (; offset < 64; offset += 7) {
+ final int b = input.read();
+ if (b == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ /**
+ * Reads a varint from the input one byte at a time, so that it does not read any bytes after the
+ * end of the varint. If you simply wrapped the stream in a CodedInputStream and used {@link
+ * #readRawVarint32(InputStream)} then you would probably end up reading past the end of the
+ * varint since CodedInputStream buffers its input.
+ */
+ static int readRawVarint32(final InputStream input) throws IOException {
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return readRawVarint32(firstByte, input);
+ }
+
+ /** A {@link CodedInputStream} implementation that uses a backing array as the input. */
+ private static final class ArrayDecoder extends CodedInputStream {
+ private final byte[] buffer;
+ private final boolean immutable;
+ private int limit;
+ private int bufferSizeAfterLimit;
+ private int pos;
+ private int startPos;
+ private int lastTag;
+ private boolean enableAliasing;
+
+ /** The absolute position of the end of the current message. */
+ private int currentLimit = Integer.MAX_VALUE;
+
+ private ArrayDecoder(final byte[] buffer, final int offset, final int len, boolean immutable) {
+ this.buffer = buffer;
+ limit = offset + len;
+ pos = offset;
+ startPos = pos;
+ this.immutable = immutable;
+ }
+
+ @Override
+ public int readTag() throws IOException {
+ if (isAtEnd()) {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = readRawVarint32();
+ if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+ // If we actually read zero (or any tag number corresponding to field
+ // number zero), that's not a valid tag.
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ return lastTag;
+ }
+
+ @Override
+ public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
+ if (lastTag != value) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ }
+
+ @Override
+ public int getLastTag() {
+ return lastTag;
+ }
+
+ @Override
+ public boolean skipField(final int tag) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ skipRawVarint();
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ skipRawBytes(FIXED_64_SIZE);
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ skipRawBytes(readRawVarint32());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ skipMessage();
+ checkLastTagWas(
+ WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormat.WIRETYPE_FIXED32:
+ skipRawBytes(FIXED_32_SIZE);
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ {
+ long value = readInt64();
+ output.writeRawVarint32(tag);
+ output.writeUInt64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_FIXED64:
+ {
+ long value = readRawLittleEndian64();
+ output.writeRawVarint32(tag);
+ output.writeFixed64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ {
+ ByteString value = readBytes();
+ output.writeRawVarint32(tag);
+ output.writeBytesNoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_START_GROUP:
+ {
+ output.writeRawVarint32(tag);
+ skipMessage(output);
+ int endtag =
+ WireFormat.makeTag(
+ WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
+ checkLastTagWas(endtag);
+ output.writeRawVarint32(endtag);
+ return true;
+ }
+ case WireFormat.WIRETYPE_END_GROUP:
+ {
+ return false;
+ }
+ case WireFormat.WIRETYPE_FIXED32:
+ {
+ int value = readRawLittleEndian32();
+ output.writeRawVarint32(tag);
+ output.writeFixed32NoTag(value);
+ return true;
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag)) {
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag, output)) {
+ return;
+ }
+ }
+ }
+
+
+ // -----------------------------------------------------------------
+
+ @Override
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readRawLittleEndian64());
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readRawLittleEndian32());
+ }
+
+ @Override
+ public long readUInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public long readInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public int readInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public long readFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ return readRawVarint64() != 0;
+ }
+
+ @Override
+ public String readString() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= (limit - pos)) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final String result = new String(buffer, pos, size, UTF_8);
+ pos += size;
+ return result;
+ }
+
+ if (size == 0) {
+ return "";
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public String readStringRequireUtf8() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= (limit - pos)) {
+ // TODO(martinrb): We could save a pass by validating while decoding.
+ if (!Utf8.isValidUtf8(buffer, pos, pos + size)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ final int tempPos = pos;
+ pos += size;
+ return new String(buffer, tempPos, size, UTF_8);
+ }
+
+ if (size == 0) {
+ return "";
+ }
+ if (size <= 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public void readGroup(
+ final int fieldNumber,
+ final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readGroup(
+ final int fieldNumber,
+ final Parser<T> parser,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ return result;
+ }
+
+ @Deprecated
+ @Override
+ public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
+ throws IOException {
+ readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ @Override
+ public void readMessage(
+ final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readMessage(
+ final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ return result;
+ }
+
+ @Override
+ public ByteString readBytes() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= (limit - pos)) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final ByteString result =
+ immutable && enableAliasing
+ ? ByteString.wrap(buffer, pos, size)
+ : ByteString.copyFrom(buffer, pos, size);
+ pos += size;
+ return result;
+ }
+ if (size == 0) {
+ return ByteString.EMPTY;
+ }
+ // Slow path: Build a byte array first then copy it.
+ return ByteString.wrap(readRawBytes(size));
+ }
+
+ @Override
+ public byte[] readByteArray() throws IOException {
+ final int size = readRawVarint32();
+ return readRawBytes(size);
+ }
+
+ @Override
+ public ByteBuffer readByteBuffer() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= (limit - pos)) {
+ // Fast path: We already have the bytes in a contiguous buffer.
+ // When aliasing is enabled, we can return a ByteBuffer pointing directly
+ // into the underlying byte array without copy if the CodedInputStream is
+ // constructed from a byte array. If aliasing is disabled or the input is
+ // from an InputStream or ByteString, we have to make a copy of the bytes.
+ ByteBuffer result =
+ !immutable && enableAliasing
+ ? ByteBuffer.wrap(buffer, pos, size).slice()
+ : ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
+ pos += size;
+ // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
+ return result;
+ }
+
+ if (size == 0) {
+ return EMPTY_BYTE_BUFFER;
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public int readUInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readEnum() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readSFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public long readSFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readSInt32() throws IOException {
+ return decodeZigZag32(readRawVarint32());
+ }
+
+ @Override
+ public long readSInt64() throws IOException {
+ return decodeZigZag64(readRawVarint64());
+ }
+
+ // =================================================================
+
+ @Override
+ public int readRawVarint32() throws IOException {
+ // See implementation notes for readRawVarint64
+ fastpath:
+ {
+ int tempPos = pos;
+
+ if (limit == tempPos) {
+ break fastpath;
+ }
+
+ final byte[] buffer = this.buffer;
+ int x;
+ if ((x = buffer[tempPos++]) >= 0) {
+ pos = tempPos;
+ return x;
+ } else if (limit - tempPos < 9) {
+ break fastpath;
+ } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
+ x ^= (~0 << 7);
+ } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
+ x ^= (~0 << 7) ^ (~0 << 14);
+ } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
+ } else {
+ int y = buffer[tempPos++];
+ x ^= y << 28;
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
+ if (y < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return (int) readRawVarint64SlowPath();
+ }
+
+ private void skipRawVarint() throws IOException {
+ if (limit - pos >= MAX_VARINT_SIZE) {
+ skipRawVarintFastPath();
+ } else {
+ skipRawVarintSlowPath();
+ }
+ }
+
+ private void skipRawVarintFastPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (buffer[pos++] >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ private void skipRawVarintSlowPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (readRawByte() >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public long readRawVarint64() throws IOException {
+ // Implementation notes:
+ //
+ // Optimized for one-byte values, expected to be common.
+ // The particular code below was selected from various candidates
+ // empirically, by winning VarintBenchmark.
+ //
+ // Sign extension of (signed) Java bytes is usually a nuisance, but
+ // we exploit it here to more easily obtain the sign of bytes read.
+ // Instead of cleaning up the sign extension bits by masking eagerly,
+ // we delay until we find the final (positive) byte, when we clear all
+ // accumulated bits with one xor. We depend on javac to constant fold.
+ fastpath:
+ {
+ int tempPos = pos;
+
+ if (limit == tempPos) {
+ break fastpath;
+ }
+
+ final byte[] buffer = this.buffer;
+ long x;
+ int y;
+ if ((y = buffer[tempPos++]) >= 0) {
+ pos = tempPos;
+ return y;
+ } else if (limit - tempPos < 9) {
+ break fastpath;
+ } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
+ x = y ^ (~0 << 7);
+ } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14));
+ } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+ } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+ } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
+ } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
+ } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49);
+ } else {
+ x ^= ((long) buffer[tempPos++] << 56);
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49)
+ ^ (~0L << 56);
+ if (x < 0L) {
+ if (buffer[tempPos++] < 0L) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return readRawVarint64SlowPath();
+ }
+
+ @Override
+ long readRawVarint64SlowPath() throws IOException {
+ long result = 0;
+ for (int shift = 0; shift < 64; shift += 7) {
+ final byte b = readRawByte();
+ result |= (long) (b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public int readRawLittleEndian32() throws IOException {
+ int tempPos = pos;
+
+ if (limit - tempPos < FIXED_32_SIZE) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ final byte[] buffer = this.buffer;
+ pos = tempPos + FIXED_32_SIZE;
+ return (((buffer[tempPos] & 0xff))
+ | ((buffer[tempPos + 1] & 0xff) << 8)
+ | ((buffer[tempPos + 2] & 0xff) << 16)
+ | ((buffer[tempPos + 3] & 0xff) << 24));
+ }
+
+ @Override
+ public long readRawLittleEndian64() throws IOException {
+ int tempPos = pos;
+
+ if (limit - tempPos < FIXED_64_SIZE) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ final byte[] buffer = this.buffer;
+ pos = tempPos + FIXED_64_SIZE;
+ return (((buffer[tempPos] & 0xffL))
+ | ((buffer[tempPos + 1] & 0xffL) << 8)
+ | ((buffer[tempPos + 2] & 0xffL) << 16)
+ | ((buffer[tempPos + 3] & 0xffL) << 24)
+ | ((buffer[tempPos + 4] & 0xffL) << 32)
+ | ((buffer[tempPos + 5] & 0xffL) << 40)
+ | ((buffer[tempPos + 6] & 0xffL) << 48)
+ | ((buffer[tempPos + 7] & 0xffL) << 56));
+ }
+
+ @Override
+ public void enableAliasing(boolean enabled) {
+ this.enableAliasing = enabled;
+ }
+
+ @Override
+ public void resetSizeCounter() {
+ startPos = pos;
+ }
+
+ @Override
+ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
+ if (byteLimit < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ byteLimit += getTotalBytesRead();
+ final int oldLimit = currentLimit;
+ if (byteLimit > oldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ currentLimit = byteLimit;
+
+ recomputeBufferSizeAfterLimit();
+
+ return oldLimit;
+ }
+
+ private void recomputeBufferSizeAfterLimit() {
+ limit += bufferSizeAfterLimit;
+ final int bufferEnd = limit - startPos;
+ if (bufferEnd > currentLimit) {
+ // Limit is in current buffer.
+ bufferSizeAfterLimit = bufferEnd - currentLimit;
+ limit -= bufferSizeAfterLimit;
+ } else {
+ bufferSizeAfterLimit = 0;
+ }
+ }
+
+ @Override
+ public void popLimit(final int oldLimit) {
+ currentLimit = oldLimit;
+ recomputeBufferSizeAfterLimit();
+ }
+
+ @Override
+ public int getBytesUntilLimit() {
+ if (currentLimit == Integer.MAX_VALUE) {
+ return -1;
+ }
+
+ return currentLimit - getTotalBytesRead();
+ }
+
+ @Override
+ public boolean isAtEnd() throws IOException {
+ return pos == limit;
+ }
+
+ @Override
+ public int getTotalBytesRead() {
+ return pos - startPos;
+ }
+
+ @Override
+ public byte readRawByte() throws IOException {
+ if (pos == limit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return buffer[pos++];
+ }
+
+ @Override
+ public byte[] readRawBytes(final int length) throws IOException {
+ if (length > 0 && length <= (limit - pos)) {
+ final int tempPos = pos;
+ pos += length;
+ return Arrays.copyOfRange(buffer, tempPos, pos);
+ }
+
+ if (length <= 0) {
+ if (length == 0) {
+ return Internal.EMPTY_BYTE_ARRAY;
+ } else {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public void skipRawBytes(final int length) throws IOException {
+ if (length >= 0 && length <= (limit - pos)) {
+ // We have all the bytes we need already.
+ pos += length;
+ return;
+ }
+
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+
+ /**
+ * A {@link CodedInputStream} implementation that uses a backing direct ByteBuffer as the input.
+ * Requires the use of {@code sun.misc.Unsafe} to perform fast reads on the buffer.
+ */
+ private static final class UnsafeDirectNioDecoder extends CodedInputStream {
+ /** The direct buffer that is backing this stream. */
+ private final ByteBuffer buffer;
+
+ /**
+ * If {@code true}, indicates that the buffer is backing a {@link ByteString} and is therefore
+ * considered to be an immutable input source.
+ */
+ private final boolean immutable;
+
+ /** The unsafe address of the content of {@link #buffer}. */
+ private final long address;
+
+ /** The unsafe address of the current read limit of the buffer. */
+ private long limit;
+
+ /** The unsafe address of the current read position of the buffer. */
+ private long pos;
+
+ /** The unsafe address of the starting read position. */
+ private long startPos;
+
+ /** The amount of available data in the buffer beyond {@link #limit}. */
+ private int bufferSizeAfterLimit;
+
+ /** The last tag that was read from this stream. */
+ private int lastTag;
+
+ /**
+ * If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]}
+ * <strong>may</strong> return slices of the underlying buffer, rather than copies.
+ */
+ private boolean enableAliasing;
+
+ /** The absolute position of the end of the current message. */
+ private int currentLimit = Integer.MAX_VALUE;
+
+ static boolean isSupported() {
+ return UnsafeUtil.hasUnsafeByteBufferOperations();
+ }
+
+ private UnsafeDirectNioDecoder(ByteBuffer buffer, boolean immutable) {
+ this.buffer = buffer;
+ address = UnsafeUtil.addressOffset(buffer);
+ limit = address + buffer.limit();
+ pos = address + buffer.position();
+ startPos = pos;
+ this.immutable = immutable;
+ }
+
+ @Override
+ public int readTag() throws IOException {
+ if (isAtEnd()) {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = readRawVarint32();
+ if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+ // If we actually read zero (or any tag number corresponding to field
+ // number zero), that's not a valid tag.
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ return lastTag;
+ }
+
+ @Override
+ public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
+ if (lastTag != value) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ }
+
+ @Override
+ public int getLastTag() {
+ return lastTag;
+ }
+
+ @Override
+ public boolean skipField(final int tag) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ skipRawVarint();
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ skipRawBytes(FIXED_64_SIZE);
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ skipRawBytes(readRawVarint32());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ skipMessage();
+ checkLastTagWas(
+ WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormat.WIRETYPE_FIXED32:
+ skipRawBytes(FIXED_32_SIZE);
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ {
+ long value = readInt64();
+ output.writeRawVarint32(tag);
+ output.writeUInt64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_FIXED64:
+ {
+ long value = readRawLittleEndian64();
+ output.writeRawVarint32(tag);
+ output.writeFixed64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ {
+ ByteString value = readBytes();
+ output.writeRawVarint32(tag);
+ output.writeBytesNoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_START_GROUP:
+ {
+ output.writeRawVarint32(tag);
+ skipMessage(output);
+ int endtag =
+ WireFormat.makeTag(
+ WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
+ checkLastTagWas(endtag);
+ output.writeRawVarint32(endtag);
+ return true;
+ }
+ case WireFormat.WIRETYPE_END_GROUP:
+ {
+ return false;
+ }
+ case WireFormat.WIRETYPE_FIXED32:
+ {
+ int value = readRawLittleEndian32();
+ output.writeRawVarint32(tag);
+ output.writeFixed32NoTag(value);
+ return true;
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag)) {
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag, output)) {
+ return;
+ }
+ }
+ }
+
+
+ // -----------------------------------------------------------------
+
+ @Override
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readRawLittleEndian64());
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readRawLittleEndian32());
+ }
+
+ @Override
+ public long readUInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public long readInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public int readInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public long readFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ return readRawVarint64() != 0;
+ }
+
+ @Override
+ public String readString() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= remaining()) {
+ // TODO(nathanmittler): Is there a way to avoid this copy?
+ byte[] bytes = copyToArray(pos, pos + size);
+ String result = new String(bytes, UTF_8);
+ pos += size;
+ return result;
+ }
+
+ if (size == 0) {
+ return "";
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public String readStringRequireUtf8() throws IOException {
+ final int size = readRawVarint32();
+ if (size >= 0 && size <= remaining()) {
+ // TODO(nathanmittler): Is there a way to avoid this copy?
+ byte[] bytes = copyToArray(pos, pos + size);
+ // TODO(martinrb): We could save a pass by validating while decoding.
+ if (!Utf8.isValidUtf8(bytes)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+
+ String result = new String(bytes, UTF_8);
+ pos += size;
+ return result;
+ }
+
+ if (size == 0) {
+ return "";
+ }
+ if (size <= 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public void readGroup(
+ final int fieldNumber,
+ final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readGroup(
+ final int fieldNumber,
+ final Parser<T> parser,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ return result;
+ }
+
+ @Deprecated
+ @Override
+ public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
+ throws IOException {
+ readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ @Override
+ public void readMessage(
+ final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readMessage(
+ final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ return result;
+ }
+
+ @Override
+ public ByteString readBytes() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= remaining()) {
+ ByteBuffer result;
+ if (immutable && enableAliasing) {
+ result = slice(pos, pos + size);
+ } else {
+ result = copy(pos, pos + size);
+ }
+ pos += size;
+ return ByteString.wrap(result);
+ }
+
+ if (size == 0) {
+ return ByteString.EMPTY;
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public byte[] readByteArray() throws IOException {
+ return readRawBytes(readRawVarint32());
+ }
+
+ @Override
+ public ByteBuffer readByteBuffer() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= remaining()) {
+ ByteBuffer result;
+ // "Immutable" implies that buffer is backing a ByteString.
+ // Disallow slicing in this case to prevent the caller from modifying the contents
+ // of the ByteString.
+ if (!immutable && enableAliasing) {
+ result = slice(pos, pos + size);
+ } else {
+ result = copy(pos, pos + size);
+ }
+ pos += size;
+ // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
+ return result;
+ }
+
+ if (size == 0) {
+ return EMPTY_BYTE_BUFFER;
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public int readUInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readEnum() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readSFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public long readSFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readSInt32() throws IOException {
+ return decodeZigZag32(readRawVarint32());
+ }
+
+ @Override
+ public long readSInt64() throws IOException {
+ return decodeZigZag64(readRawVarint64());
+ }
+
+ // =================================================================
+
+ @Override
+ public int readRawVarint32() throws IOException {
+ // See implementation notes for readRawVarint64
+ fastpath:
+ {
+ long tempPos = pos;
+
+ if (limit == tempPos) {
+ break fastpath;
+ }
+
+ int x;
+ if ((x = UnsafeUtil.getByte(tempPos++)) >= 0) {
+ pos = tempPos;
+ return x;
+ } else if (limit - tempPos < 9) {
+ break fastpath;
+ } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
+ x ^= (~0 << 7);
+ } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
+ x ^= (~0 << 7) ^ (~0 << 14);
+ } else if ((x ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
+ } else {
+ int y = UnsafeUtil.getByte(tempPos++);
+ x ^= y << 28;
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
+ if (y < 0
+ && UnsafeUtil.getByte(tempPos++) < 0
+ && UnsafeUtil.getByte(tempPos++) < 0
+ && UnsafeUtil.getByte(tempPos++) < 0
+ && UnsafeUtil.getByte(tempPos++) < 0
+ && UnsafeUtil.getByte(tempPos++) < 0) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return (int) readRawVarint64SlowPath();
+ }
+
+ private void skipRawVarint() throws IOException {
+ if (remaining() >= MAX_VARINT_SIZE) {
+ skipRawVarintFastPath();
+ } else {
+ skipRawVarintSlowPath();
+ }
+ }
+
+ private void skipRawVarintFastPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (UnsafeUtil.getByte(pos++) >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ private void skipRawVarintSlowPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (readRawByte() >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public long readRawVarint64() throws IOException {
+ // Implementation notes:
+ //
+ // Optimized for one-byte values, expected to be common.
+ // The particular code below was selected from various candidates
+ // empirically, by winning VarintBenchmark.
+ //
+ // Sign extension of (signed) Java bytes is usually a nuisance, but
+ // we exploit it here to more easily obtain the sign of bytes read.
+ // Instead of cleaning up the sign extension bits by masking eagerly,
+ // we delay until we find the final (positive) byte, when we clear all
+ // accumulated bits with one xor. We depend on javac to constant fold.
+ fastpath:
+ {
+ long tempPos = pos;
+
+ if (limit == tempPos) {
+ break fastpath;
+ }
+
+ long x;
+ int y;
+ if ((y = UnsafeUtil.getByte(tempPos++)) >= 0) {
+ pos = tempPos;
+ return y;
+ } else if (limit - tempPos < 9) {
+ break fastpath;
+ } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 7)) < 0) {
+ x = y ^ (~0 << 7);
+ } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 14)) >= 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14));
+ } else if ((y ^= (UnsafeUtil.getByte(tempPos++) << 21)) < 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+ } else if ((x = y ^ ((long) UnsafeUtil.getByte(tempPos++) << 28)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+ } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 35)) < 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
+ } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 42)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
+ } else if ((x ^= ((long) UnsafeUtil.getByte(tempPos++) << 49)) < 0L) {
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49);
+ } else {
+ x ^= ((long) UnsafeUtil.getByte(tempPos++) << 56);
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49)
+ ^ (~0L << 56);
+ if (x < 0L) {
+ if (UnsafeUtil.getByte(tempPos++) < 0L) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return readRawVarint64SlowPath();
+ }
+
+ @Override
+ long readRawVarint64SlowPath() throws IOException {
+ long result = 0;
+ for (int shift = 0; shift < 64; shift += 7) {
+ final byte b = readRawByte();
+ result |= (long) (b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public int readRawLittleEndian32() throws IOException {
+ long tempPos = pos;
+
+ if (limit - tempPos < FIXED_32_SIZE) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ pos = tempPos + FIXED_32_SIZE;
+ return (((UnsafeUtil.getByte(tempPos) & 0xff))
+ | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
+ | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
+ | ((UnsafeUtil.getByte(tempPos + 3) & 0xff) << 24));
+ }
+
+ @Override
+ public long readRawLittleEndian64() throws IOException {
+ long tempPos = pos;
+
+ if (limit - tempPos < FIXED_64_SIZE) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ pos = tempPos + FIXED_64_SIZE;
+ return (((UnsafeUtil.getByte(tempPos) & 0xffL))
+ | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
+ | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
+ | ((UnsafeUtil.getByte(tempPos + 3) & 0xffL) << 24)
+ | ((UnsafeUtil.getByte(tempPos + 4) & 0xffL) << 32)
+ | ((UnsafeUtil.getByte(tempPos + 5) & 0xffL) << 40)
+ | ((UnsafeUtil.getByte(tempPos + 6) & 0xffL) << 48)
+ | ((UnsafeUtil.getByte(tempPos + 7) & 0xffL) << 56));
+ }
+
+ @Override
+ public void enableAliasing(boolean enabled) {
+ this.enableAliasing = enabled;
+ }
+
+ @Override
+ public void resetSizeCounter() {
+ startPos = pos;
+ }
+
+ @Override
+ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
+ if (byteLimit < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ byteLimit += getTotalBytesRead();
+ final int oldLimit = currentLimit;
+ if (byteLimit > oldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ currentLimit = byteLimit;
+
+ recomputeBufferSizeAfterLimit();
+
+ return oldLimit;
+ }
+
+ @Override
+ public void popLimit(final int oldLimit) {
+ currentLimit = oldLimit;
+ recomputeBufferSizeAfterLimit();
+ }
+
+ @Override
+ public int getBytesUntilLimit() {
+ if (currentLimit == Integer.MAX_VALUE) {
+ return -1;
+ }
+
+ return currentLimit - getTotalBytesRead();
+ }
+
+ @Override
+ public boolean isAtEnd() throws IOException {
+ return pos == limit;
+ }
+
+ @Override
+ public int getTotalBytesRead() {
+ return (int) (pos - startPos);
+ }
+
+ @Override
+ public byte readRawByte() throws IOException {
+ if (pos == limit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return UnsafeUtil.getByte(pos++);
+ }
+
+ @Override
+ public byte[] readRawBytes(final int length) throws IOException {
+ if (length >= 0 && length <= remaining()) {
+ byte[] bytes = new byte[length];
+ slice(pos, pos + length).get(bytes);
+ pos += length;
+ return bytes;
+ }
+
+ if (length <= 0) {
+ if (length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ } else {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ }
+
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ @Override
+ public void skipRawBytes(final int length) throws IOException {
+ if (length >= 0 && length <= remaining()) {
+ // We have all the bytes we need already.
+ pos += length;
+ return;
+ }
+
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ private void recomputeBufferSizeAfterLimit() {
+ limit += bufferSizeAfterLimit;
+ final int bufferEnd = (int) (limit - startPos);
+ if (bufferEnd > currentLimit) {
+ // Limit is in current buffer.
+ bufferSizeAfterLimit = bufferEnd - currentLimit;
+ limit -= bufferSizeAfterLimit;
+ } else {
+ bufferSizeAfterLimit = 0;
+ }
+ }
+
+ private int remaining() {
+ return (int) (limit - pos);
+ }
+
+ private int bufferPos(long pos) {
+ return (int) (pos - address);
+ }
+
+ private ByteBuffer slice(long begin, long end) throws IOException {
+ int prevPos = buffer.position();
+ int prevLimit = buffer.limit();
+ try {
+ buffer.position(bufferPos(begin));
+ buffer.limit(bufferPos(end));
+ return buffer.slice();
+ } catch (IllegalArgumentException e) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } finally {
+ buffer.position(prevPos);
+ buffer.limit(prevLimit);
+ }
+ }
+
+ private ByteBuffer copy(long begin, long end) throws IOException {
+ return ByteBuffer.wrap(copyToArray(begin, end));
+ }
+
+ private byte[] copyToArray(long begin, long end) throws IOException {
+ int prevPos = buffer.position();
+ int prevLimit = buffer.limit();
+ try {
+ buffer.position(bufferPos(begin));
+ buffer.limit(bufferPos(end));
+ byte[] bytes = new byte[(int) (end - begin)];
+ buffer.get(bytes);
+ return bytes;
+ } catch (IllegalArgumentException e) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } finally {
+ buffer.position(prevPos);
+ buffer.limit(prevLimit);
+ }
+ }
+ }
+
+ /**
+ * Implementation of {@link CodedInputStream} that uses an {@link InputStream} as the data source.
+ */
+ private static final class StreamDecoder extends CodedInputStream {
+ private final InputStream input;
+ private final byte[] buffer;
+ /** bufferSize represents how many bytes are currently filled in the buffer */
+ private int bufferSize;
+
+ private int bufferSizeAfterLimit;
+ private int pos;
+ private int lastTag;
+
+ /**
+ * The total number of bytes read before the current buffer. The total bytes read up to the
+ * current position can be computed as {@code totalBytesRetired + pos}. This value may be
+ * negative if reading started in the middle of the current buffer (e.g. if the constructor that
+ * takes a byte array and an offset was used).
+ */
+ private int totalBytesRetired;
+
+ /** The absolute position of the end of the current message. */
+ private int currentLimit = Integer.MAX_VALUE;
+
+ private StreamDecoder(final InputStream input, int bufferSize) {
+ checkNotNull(input, "input");
+ this.input = input;
+ this.buffer = new byte[bufferSize];
+ this.bufferSize = 0;
+ pos = 0;
+ totalBytesRetired = 0;
+ }
+
+ @Override
+ public int readTag() throws IOException {
+ if (isAtEnd()) {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = readRawVarint32();
+ if (WireFormat.getTagFieldNumber(lastTag) == 0) {
+ // If we actually read zero (or any tag number corresponding to field
+ // number zero), that's not a valid tag.
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ return lastTag;
+ }
+
+ @Override
+ public void checkLastTagWas(final int value) throws InvalidProtocolBufferException {
+ if (lastTag != value) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ }
+
+ @Override
+ public int getLastTag() {
+ return lastTag;
+ }
+
+ @Override
+ public boolean skipField(final int tag) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ skipRawVarint();
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ skipRawBytes(FIXED_64_SIZE);
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ skipRawBytes(readRawVarint32());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ skipMessage();
+ checkLastTagWas(
+ WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP));
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormat.WIRETYPE_FIXED32:
+ skipRawBytes(FIXED_32_SIZE);
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public boolean skipField(final int tag, final CodedOutputStream output) throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ {
+ long value = readInt64();
+ output.writeRawVarint32(tag);
+ output.writeUInt64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_FIXED64:
+ {
+ long value = readRawLittleEndian64();
+ output.writeRawVarint32(tag);
+ output.writeFixed64NoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ {
+ ByteString value = readBytes();
+ output.writeRawVarint32(tag);
+ output.writeBytesNoTag(value);
+ return true;
+ }
+ case WireFormat.WIRETYPE_START_GROUP:
+ {
+ output.writeRawVarint32(tag);
+ skipMessage(output);
+ int endtag =
+ WireFormat.makeTag(
+ WireFormat.getTagFieldNumber(tag), WireFormat.WIRETYPE_END_GROUP);
+ checkLastTagWas(endtag);
+ output.writeRawVarint32(endtag);
+ return true;
+ }
+ case WireFormat.WIRETYPE_END_GROUP:
+ {
+ return false;
+ }
+ case WireFormat.WIRETYPE_FIXED32:
+ {
+ int value = readRawLittleEndian32();
+ output.writeRawVarint32(tag);
+ output.writeFixed32NoTag(value);
+ return true;
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public void skipMessage() throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag)) {
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void skipMessage(CodedOutputStream output) throws IOException {
+ while (true) {
+ final int tag = readTag();
+ if (tag == 0 || !skipField(tag, output)) {
+ return;
+ }
+ }
+ }
+
+ /** Collects the bytes skipped and returns the data in a ByteBuffer. */
+ private class SkippedDataSink implements RefillCallback {
+ private int lastPos = pos;
+ private ByteArrayOutputStream byteArrayStream;
+
+ @Override
+ public void onRefill() {
+ if (byteArrayStream == null) {
+ byteArrayStream = new ByteArrayOutputStream();
+ }
+ byteArrayStream.write(buffer, lastPos, pos - lastPos);
+ lastPos = 0;
+ }
+
+ /** Gets skipped data in a ByteBuffer. This method should only be called once. */
+ ByteBuffer getSkippedData() {
+ if (byteArrayStream == null) {
+ return ByteBuffer.wrap(buffer, lastPos, pos - lastPos);
+ } else {
+ byteArrayStream.write(buffer, lastPos, pos);
+ return ByteBuffer.wrap(byteArrayStream.toByteArray());
+ }
+ }
+ }
+
+
+ // -----------------------------------------------------------------
+
+ @Override
+ public double readDouble() throws IOException {
+ return Double.longBitsToDouble(readRawLittleEndian64());
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return Float.intBitsToFloat(readRawLittleEndian32());
+ }
+
+ @Override
+ public long readUInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public long readInt64() throws IOException {
+ return readRawVarint64();
+ }
+
+ @Override
+ public int readInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public long readFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ return readRawVarint64() != 0;
+ }
+
+ @Override
+ public String readString() throws IOException {
+ final int size = readRawVarint32();
+ if (size > 0 && size <= (bufferSize - pos)) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final String result = new String(buffer, pos, size, UTF_8);
+ pos += size;
+ return result;
+ }
+ if (size == 0) {
+ return "";
+ }
+ if (size <= bufferSize) {
+ refillBuffer(size);
+ String result = new String(buffer, pos, size, UTF_8);
+ pos += size;
+ return result;
+ }
+ // Slow path: Build a byte array first then copy it.
+ return new String(readRawBytesSlowPath(size), UTF_8);
+ }
+
+ @Override
+ public String readStringRequireUtf8() throws IOException {
+ final int size = readRawVarint32();
+ final byte[] bytes;
+ final int oldPos = pos;
+ final int tempPos;
+ if (size <= (bufferSize - oldPos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ bytes = buffer;
+ pos = oldPos + size;
+ tempPos = oldPos;
+ } else if (size == 0) {
+ return "";
+ } else if (size <= bufferSize) {
+ refillBuffer(size);
+ bytes = buffer;
+ tempPos = 0;
+ pos = tempPos + size;
+ } else {
+ // Slow path: Build a byte array first then copy it.
+ bytes = readRawBytesSlowPath(size);
+ tempPos = 0;
+ }
+ // TODO(martinrb): We could save a pass by validating while decoding.
+ if (!Utf8.isValidUtf8(bytes, tempPos, tempPos + size)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ return new String(bytes, tempPos, size, UTF_8);
+ }
+
+ @Override
+ public void readGroup(
+ final int fieldNumber,
+ final MessageLite.Builder builder,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readGroup(
+ final int fieldNumber,
+ final Parser<T> parser,
+ final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ --recursionDepth;
+ return result;
+ }
+
+ @Deprecated
+ @Override
+ public void readUnknownGroup(final int fieldNumber, final MessageLite.Builder builder)
+ throws IOException {
+ readGroup(fieldNumber, builder, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ @Override
+ public void readMessage(
+ final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ builder.mergeFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ }
+
+
+ @Override
+ public <T extends MessageLite> T readMessage(
+ final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
+ int length = readRawVarint32();
+ if (recursionDepth >= recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+ final int oldLimit = pushLimit(length);
+ ++recursionDepth;
+ T result = parser.parsePartialFrom(this, extensionRegistry);
+ checkLastTagWas(0);
+ --recursionDepth;
+ popLimit(oldLimit);
+ return result;
+ }
+
+ @Override
+ public ByteString readBytes() throws IOException {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - pos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final ByteString result = ByteString.copyFrom(buffer, pos, size);
+ pos += size;
+ return result;
+ }
+ if (size == 0) {
+ return ByteString.EMPTY;
+ }
+ // Slow path: Build a byte array first then copy it.
+ return ByteString.wrap(readRawBytesSlowPath(size));
+ }
+
+ @Override
+ public byte[] readByteArray() throws IOException {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - pos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer, so
+ // just copy directly from it.
+ final byte[] result = Arrays.copyOfRange(buffer, pos, pos + size);
+ pos += size;
+ return result;
+ } else {
+ // Slow path: Build a byte array first then copy it.
+ return readRawBytesSlowPath(size);
+ }
+ }
+
+ @Override
+ public ByteBuffer readByteBuffer() throws IOException {
+ final int size = readRawVarint32();
+ if (size <= (bufferSize - pos) && size > 0) {
+ // Fast path: We already have the bytes in a contiguous buffer.
+ ByteBuffer result = ByteBuffer.wrap(Arrays.copyOfRange(buffer, pos, pos + size));
+ pos += size;
+ return result;
+ }
+ if (size == 0) {
+ return Internal.EMPTY_BYTE_BUFFER;
+ }
+ // Slow path: Build a byte array first then copy it.
+ return ByteBuffer.wrap(readRawBytesSlowPath(size));
+ }
+
+ @Override
+ public int readUInt32() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readEnum() throws IOException {
+ return readRawVarint32();
+ }
+
+ @Override
+ public int readSFixed32() throws IOException {
+ return readRawLittleEndian32();
+ }
+
+ @Override
+ public long readSFixed64() throws IOException {
+ return readRawLittleEndian64();
+ }
+
+ @Override
+ public int readSInt32() throws IOException {
+ return decodeZigZag32(readRawVarint32());
+ }
+
+ @Override
+ public long readSInt64() throws IOException {
+ return decodeZigZag64(readRawVarint64());
+ }
+
+ // =================================================================
+
+ @Override
+ public int readRawVarint32() throws IOException {
+ // See implementation notes for readRawVarint64
+ fastpath:
+ {
+ int tempPos = pos;
+
+ if (bufferSize == tempPos) {
+ break fastpath;
+ }
+
+ final byte[] buffer = this.buffer;
+ int x;
+ if ((x = buffer[tempPos++]) >= 0) {
+ pos = tempPos;
+ return x;
+ } else if (bufferSize - tempPos < 9) {
+ break fastpath;
+ } else if ((x ^= (buffer[tempPos++] << 7)) < 0) {
+ x ^= (~0 << 7);
+ } else if ((x ^= (buffer[tempPos++] << 14)) >= 0) {
+ x ^= (~0 << 7) ^ (~0 << 14);
+ } else if ((x ^= (buffer[tempPos++] << 21)) < 0) {
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
+ } else {
+ int y = buffer[tempPos++];
+ x ^= y << 28;
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
+ if (y < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0
+ && buffer[tempPos++] < 0) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return (int) readRawVarint64SlowPath();
+ }
+
+ private void skipRawVarint() throws IOException {
+ if (bufferSize - pos >= MAX_VARINT_SIZE) {
+ skipRawVarintFastPath();
+ } else {
+ skipRawVarintSlowPath();
+ }
+ }
+
+ private void skipRawVarintFastPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (buffer[pos++] >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ private void skipRawVarintSlowPath() throws IOException {
+ for (int i = 0; i < MAX_VARINT_SIZE; i++) {
+ if (readRawByte() >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public long readRawVarint64() throws IOException {
+ // Implementation notes:
+ //
+ // Optimized for one-byte values, expected to be common.
+ // The particular code below was selected from various candidates
+ // empirically, by winning VarintBenchmark.
+ //
+ // Sign extension of (signed) Java bytes is usually a nuisance, but
+ // we exploit it here to more easily obtain the sign of bytes read.
+ // Instead of cleaning up the sign extension bits by masking eagerly,
+ // we delay until we find the final (positive) byte, when we clear all
+ // accumulated bits with one xor. We depend on javac to constant fold.
+ fastpath:
+ {
+ int tempPos = pos;
+
+ if (bufferSize == tempPos) {
+ break fastpath;
+ }
+
+ final byte[] buffer = this.buffer;
+ long x;
+ int y;
+ if ((y = buffer[tempPos++]) >= 0) {
+ pos = tempPos;
+ return y;
+ } else if (bufferSize - tempPos < 9) {
+ break fastpath;
+ } else if ((y ^= (buffer[tempPos++] << 7)) < 0) {
+ x = y ^ (~0 << 7);
+ } else if ((y ^= (buffer[tempPos++] << 14)) >= 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14));
+ } else if ((y ^= (buffer[tempPos++] << 21)) < 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+ } else if ((x = y ^ ((long) buffer[tempPos++] << 28)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+ } else if ((x ^= ((long) buffer[tempPos++] << 35)) < 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
+ } else if ((x ^= ((long) buffer[tempPos++] << 42)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
+ } else if ((x ^= ((long) buffer[tempPos++] << 49)) < 0L) {
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49);
+ } else {
+ x ^= ((long) buffer[tempPos++] << 56);
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49)
+ ^ (~0L << 56);
+ if (x < 0L) {
+ if (buffer[tempPos++] < 0L) {
+ break fastpath; // Will throw malformedVarint()
+ }
+ }
+ }
+ pos = tempPos;
+ return x;
+ }
+ return readRawVarint64SlowPath();
+ }
+
+ @Override
+ long readRawVarint64SlowPath() throws IOException {
+ long result = 0;
+ for (int shift = 0; shift < 64; shift += 7) {
+ final byte b = readRawByte();
+ result |= (long) (b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ @Override
+ public int readRawLittleEndian32() throws IOException {
+ int tempPos = pos;
+
+ if (bufferSize - tempPos < FIXED_32_SIZE) {
+ refillBuffer(FIXED_32_SIZE);
+ tempPos = pos;
+ }
+
+ final byte[] buffer = this.buffer;
+ pos = tempPos + FIXED_32_SIZE;
+ return (((buffer[tempPos] & 0xff))
+ | ((buffer[tempPos + 1] & 0xff) << 8)
+ | ((buffer[tempPos + 2] & 0xff) << 16)
+ | ((buffer[tempPos + 3] & 0xff) << 24));
+ }
+
+ @Override
+ public long readRawLittleEndian64() throws IOException {
+ int tempPos = pos;
+
+ if (bufferSize - tempPos < FIXED_64_SIZE) {
+ refillBuffer(FIXED_64_SIZE);
+ tempPos = pos;
+ }
+
+ final byte[] buffer = this.buffer;
+ pos = tempPos + FIXED_64_SIZE;
+ return (((buffer[tempPos] & 0xffL))
+ | ((buffer[tempPos + 1] & 0xffL) << 8)
+ | ((buffer[tempPos + 2] & 0xffL) << 16)
+ | ((buffer[tempPos + 3] & 0xffL) << 24)
+ | ((buffer[tempPos + 4] & 0xffL) << 32)
+ | ((buffer[tempPos + 5] & 0xffL) << 40)
+ | ((buffer[tempPos + 6] & 0xffL) << 48)
+ | ((buffer[tempPos + 7] & 0xffL) << 56));
+ }
+
+ // -----------------------------------------------------------------
+
+ @Override
+ public void enableAliasing(boolean enabled) {
+ // TODO(nathanmittler): Ideally we should throw here. Do nothing for backward compatibility.
+ }
+
+ @Override
+ public void resetSizeCounter() {
+ totalBytesRetired = -pos;
+ }
+
+ @Override
+ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
+ if (byteLimit < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+ byteLimit += totalBytesRetired + pos;
+ final int oldLimit = currentLimit;
+ if (byteLimit > oldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ currentLimit = byteLimit;
+
+ recomputeBufferSizeAfterLimit();
+
+ return oldLimit;
+ }
+
+ private void recomputeBufferSizeAfterLimit() {
+ bufferSize += bufferSizeAfterLimit;
+ final int bufferEnd = totalBytesRetired + bufferSize;
+ if (bufferEnd > currentLimit) {
+ // Limit is in current buffer.
+ bufferSizeAfterLimit = bufferEnd - currentLimit;
+ bufferSize -= bufferSizeAfterLimit;
+ } else {
+ bufferSizeAfterLimit = 0;
+ }
+ }
+
+ @Override
+ public void popLimit(final int oldLimit) {
+ currentLimit = oldLimit;
+ recomputeBufferSizeAfterLimit();
+ }
+
+ @Override
+ public int getBytesUntilLimit() {
+ if (currentLimit == Integer.MAX_VALUE) {
+ return -1;
+ }
+
+ final int currentAbsolutePosition = totalBytesRetired + pos;
+ return currentLimit - currentAbsolutePosition;
+ }
+
+ @Override
+ public boolean isAtEnd() throws IOException {
+ return pos == bufferSize && !tryRefillBuffer(1);
+ }
+
+ @Override
+ public int getTotalBytesRead() {
+ return totalBytesRetired + pos;
+ }
+
+ private interface RefillCallback {
+ void onRefill();
+ }
+
+ private RefillCallback refillCallback = null;
+
+ /**
+ * Reads more bytes from the input, making at least {@code n} bytes available in the buffer.
+ * Caller must ensure that the requested space is not yet available, and that the requested
+ * space is less than BUFFER_SIZE.
+ *
+ * @throws InvalidProtocolBufferException The end of the stream or the current limit was
+ * reached.
+ */
+ private void refillBuffer(int n) throws IOException {
+ if (!tryRefillBuffer(n)) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+
+ /**
+ * Tries to read more bytes from the input, making at least {@code n} bytes available in the
+ * buffer. Caller must ensure that the requested space is not yet available, and that the
+ * requested space is less than BUFFER_SIZE.
+ *
+ * @return {@code true} if the bytes could be made available; {@code false} if the end of the
+ * stream or the current limit was reached.
+ */
+ private boolean tryRefillBuffer(int n) throws IOException {
+ if (pos + n <= bufferSize) {
+ throw new IllegalStateException(
+ "refillBuffer() called when " + n + " bytes were already available in buffer");
+ }
+
+ if (totalBytesRetired + pos + n > currentLimit) {
+ // Oops, we hit a limit.
+ return false;
+ }
+
+ if (refillCallback != null) {
+ refillCallback.onRefill();
+ }
+
+ int tempPos = pos;
+ if (tempPos > 0) {
+ if (bufferSize > tempPos) {
+ System.arraycopy(buffer, tempPos, buffer, 0, bufferSize - tempPos);
+ }
+ totalBytesRetired += tempPos;
+ bufferSize -= tempPos;
+ pos = 0;
+ }
+
+ int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
+ if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
+ throw new IllegalStateException(
+ "InputStream#read(byte[]) returned invalid result: "
+ + bytesRead
+ + "\nThe InputStream implementation is buggy.");
+ }
+ if (bytesRead > 0) {
+ bufferSize += bytesRead;
+ // Integer-overflow-conscious check against sizeLimit
+ if (totalBytesRetired + n - sizeLimit > 0) {
+ throw InvalidProtocolBufferException.sizeLimitExceeded();
+ }
+ recomputeBufferSizeAfterLimit();
+ return (bufferSize >= n) ? true : tryRefillBuffer(n);
+ }
+
+ return false;
+ }
+
+ @Override
+ public byte readRawByte() throws IOException {
+ if (pos == bufferSize) {
+ refillBuffer(1);
+ }
+ return buffer[pos++];
+ }
+
+ @Override
+ public byte[] readRawBytes(final int size) throws IOException {
+ final int tempPos = pos;
+ if (size <= (bufferSize - tempPos) && size > 0) {
+ pos = tempPos + size;
+ return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
+ } else {
+ return readRawBytesSlowPath(size);
+ }
+ }
+
+ /**
+ * Exactly like readRawBytes, but caller must have already checked the fast path: (size <=
+ * (bufferSize - pos) && size > 0)
+ */
+ private byte[] readRawBytesSlowPath(final int size) throws IOException {
+ if (size == 0) {
+ return Internal.EMPTY_BYTE_ARRAY;
+ }
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+
+ // Integer-overflow-conscious check that the message size so far has not exceeded sizeLimit.
+ int currentMessageSize = totalBytesRetired + pos + size;
+ if (currentMessageSize - sizeLimit > 0) {
+ throw InvalidProtocolBufferException.sizeLimitExceeded();
+ }
+
+ // Verify that the message size so far has not exceeded currentLimit.
+ if (currentMessageSize > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - totalBytesRetired - pos);
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ final int originalBufferPos = pos;
+ final int bufferedBytes = bufferSize - pos;
+
+ // Mark the current buffer consumed.
+ totalBytesRetired += bufferSize;
+ pos = 0;
+ bufferSize = 0;
+
+ // Determine the number of bytes we need to read from the input stream.
+ int sizeLeft = size - bufferedBytes;
+ // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
+ if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
+ // Either the bytes we need are known to be available, or the required buffer is
+ // within an allowed threshold - go ahead and allocate the buffer now.
+ final byte[] bytes = new byte[size];
+
+ // Copy all of the buffered bytes to the result buffer.
+ System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+
+ // Fill the remaining bytes from the input stream.
+ int tempPos = bufferedBytes;
+ while (tempPos < bytes.length) {
+ int n = input.read(bytes, tempPos, size - tempPos);
+ if (n == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ totalBytesRetired += n;
+ tempPos += n;
+ }
+
+ return bytes;
+ }
+
+ // The size is very large. For security reasons, we can't allocate the
+ // entire byte array yet. The size comes directly from the input, so a
+ // maliciously-crafted message could provide a bogus very large size in
+ // order to trick the app into allocating a lot of memory. We avoid this
+ // by allocating and reading only a small chunk at a time, so that the
+ // malicious message must actually *be* extremely large to cause
+ // problems. Meanwhile, we limit the allowed size of a message elsewhere.
+ final List<byte[]> chunks = new ArrayList<byte[]>();
+
+ while (sizeLeft > 0) {
+ // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
+ final byte[] chunk = new byte[Math.min(sizeLeft, DEFAULT_BUFFER_SIZE)];
+ int tempPos = 0;
+ while (tempPos < chunk.length) {
+ final int n = input.read(chunk, tempPos, chunk.length - tempPos);
+ if (n == -1) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ totalBytesRetired += n;
+ tempPos += n;
+ }
+ sizeLeft -= chunk.length;
+ chunks.add(chunk);
+ }
+
+ // OK, got everything. Now concatenate it all into one buffer.
+ final byte[] bytes = new byte[size];
+
+ // Start by copying the leftover bytes from this.buffer.
+ System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+
+ // And now all the chunks.
+ int tempPos = bufferedBytes;
+ for (final byte[] chunk : chunks) {
+ System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
+ tempPos += chunk.length;
+ }
+
+ // Done.
+ return bytes;
+ }
+
+ @Override
+ public void skipRawBytes(final int size) throws IOException {
+ if (size <= (bufferSize - pos) && size >= 0) {
+ // We have all the bytes we need already.
+ pos += size;
+ } else {
+ skipRawBytesSlowPath(size);
+ }
+ }
+
+ /**
+ * Exactly like skipRawBytes, but caller must have already checked the fast path: (size <=
+ * (bufferSize - pos) && size >= 0)
+ */
+ private void skipRawBytesSlowPath(final int size) throws IOException {
+ if (size < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ }
+
+ if (totalBytesRetired + pos + size > currentLimit) {
+ // Read to the end of the stream anyway.
+ skipRawBytes(currentLimit - totalBytesRetired - pos);
+ // Then fail.
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ // Skipping more bytes than are in the buffer. First skip what we have.
+ int tempPos = bufferSize - pos;
+ pos = bufferSize;
+
+ // Keep refilling the buffer until we get to the point we wanted to skip to.
+ // This has the side effect of ensuring the limits are updated correctly.
+ refillBuffer(1);
+ while (size - tempPos > bufferSize) {
+ tempPos += bufferSize;
+ pos = bufferSize;
+ refillBuffer(1);
+ }
+
+ pos = size - tempPos;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
new file mode 100644
index 0000000000..3e32c2c536
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -0,0 +1,3001 @@
+// 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 static com.google.protobuf.WireFormat.FIXED_32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
+import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
+import static java.lang.Math.max;
+
+import com.google.protobuf.Utf8.UnpairedSurrogateException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Encodes and writes protocol message fields.
+ *
+ * <p>This class contains two kinds of methods: methods that write specific
+ * protocol message constructs and field types (e.g. {@link #writeTag} and
+ * {@link #writeInt32}) and methods that write low-level values (e.g.
+ * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are
+ * writing encoded protocol messages, you should use the former methods, but if
+ * you are writing some other format of your own design, use the latter.
+ *
+ * <p>This class is totally unsynchronized.
+ */
+public abstract class CodedOutputStream extends ByteOutput {
+ private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
+ private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations();
+ private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset();
+
+ /**
+ * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
+ */
+ @Deprecated
+ public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
+
+ /**
+ * The buffer size used in {@link #newInstance(OutputStream)}.
+ */
+ public static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ /**
+ * Returns the buffer size to efficiently write dataLength bytes to this
+ * CodedOutputStream. Used by AbstractMessageLite.
+ *
+ * @return the buffer size to efficiently write dataLength bytes to this
+ * CodedOutputStream.
+ */
+ static int computePreferredBufferSize(int dataLength) {
+ if (dataLength > DEFAULT_BUFFER_SIZE) {
+ return DEFAULT_BUFFER_SIZE;
+ }
+ return dataLength;
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}.
+ *
+ * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+ * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+ * difficult to debug.
+ */
+ public static CodedOutputStream newInstance(final OutputStream output) {
+ return newInstance(output, DEFAULT_BUFFER_SIZE);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given
+ * buffer size.
+ *
+ * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+ * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+ * difficult to debug.
+ */
+ public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) {
+ return new OutputStreamEncoder(output, bufferSize);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes directly to the given
+ * byte array. If more bytes are written than fit in the array,
+ * {@link OutOfSpaceException} will be thrown. Writing directly to a flat
+ * array is faster than writing to an {@code OutputStream}. See also
+ * {@link ByteString#newCodedBuilder}.
+ */
+ public static CodedOutputStream newInstance(final byte[] flatArray) {
+ return newInstance(flatArray, 0, flatArray.length);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes directly to the given
+ * byte array slice. If more bytes are written than fit in the slice,
+ * {@link OutOfSpaceException} will be thrown. Writing directly to a flat
+ * array is faster than writing to an {@code OutputStream}. See also
+ * {@link ByteString#newCodedBuilder}.
+ */
+ public static CodedOutputStream newInstance(
+ final byte[] flatArray, final int offset, final int length) {
+ return new ArrayEncoder(flatArray, offset, length);
+ }
+
+ /** Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}. */
+ public static CodedOutputStream newInstance(ByteBuffer buffer) {
+ if (buffer.hasArray()) {
+ return new HeapNioEncoder(buffer);
+ }
+ if (buffer.isDirect() && !buffer.isReadOnly()) {
+ return UnsafeDirectNioEncoder.isSupported()
+ ? newUnsafeInstance(buffer)
+ : newSafeInstance(buffer);
+ }
+ throw new IllegalArgumentException("ByteBuffer is read-only");
+ }
+
+ /** For testing purposes only. */
+ static CodedOutputStream newUnsafeInstance(ByteBuffer buffer) {
+ return new UnsafeDirectNioEncoder(buffer);
+ }
+
+ /** For testing purposes only. */
+ static CodedOutputStream newSafeInstance(ByteBuffer buffer) {
+ return new SafeDirectNioEncoder(buffer);
+ }
+
+ /**
+ * Configures serialization to be deterministic.
+ *
+ * <p>The deterministic serialization guarantees that for a given binary, equal (defined by the
+ * {@code equals()} methods in protos) messages will always be serialized to the same bytes. This
+ * implies:
+ *
+ * <ul>
+ * <li>repeated serialization of a message will return the same bytes
+ * <li>different processes of the same binary (which may be executing on different machines) will
+ * serialize equal messages to the same bytes.
+ * </ul>
+ *
+ * <p>Note the deterministic serialization is NOT canonical across languages; it is also unstable
+ * across different builds with schema changes due to unknown fields. Users who need canonical
+ * serialization, e.g. persistent storage in a canonical form, fingerprinting, etc, should define
+ * their own canonicalization specification and implement the serializer using reflection APIs
+ * rather than relying on this API.
+ *
+ * <p> Once set, the serializer will: (Note this is an implementation detail and may subject to
+ * change in the future)
+ *
+ * <ul>
+ * <li> sort map entries by keys in lexicographical order or numerical order. Note: For string
+ * keys, the order is based on comparing the Unicode value of each character in the strings.
+ * The order may be different from the deterministic serialization in other languages where
+ * maps are sorted on the lexicographical order of the UTF8 encoded keys.
+ * </ul>
+ */
+ void useDeterministicSerialization() {
+ serializationDeterministic = true;
+ }
+
+ boolean isSerializationDeterministic() {
+ return serializationDeterministic;
+ }
+ private boolean serializationDeterministic;
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
+ *
+ * @deprecated the size parameter is no longer used since use of an internal buffer is useless
+ * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)}
+ * instead.
+ */
+ @Deprecated
+ public static CodedOutputStream newInstance(ByteBuffer byteBuffer,
+ @SuppressWarnings("unused") int unused) {
+ return newInstance(byteBuffer);
+ }
+
+ /**
+ * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}.
+ *
+ * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
+ * so may result in corrupted data, which would be difficult to debug.
+ *
+ * @param byteOutput the output target for encoded bytes.
+ * @param bufferSize the size of the internal scratch buffer to be used for string encoding.
+ * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded
+ * string.
+ */
+ static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) {
+ if (bufferSize < 0) {
+ throw new IllegalArgumentException("bufferSize must be positive");
+ }
+
+ return new ByteOutputEncoder(byteOutput, bufferSize);
+ }
+
+ // Disallow construction outside of this class.
+ private CodedOutputStream() {
+ }
+
+ // -----------------------------------------------------------------
+
+ /** Encode and write a tag. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeTag(int fieldNumber, int wireType) throws IOException;
+
+ /** Write an {@code int32} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeInt32(int fieldNumber, int value) throws IOException;
+
+ /** Write a {@code uint32} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt32(int fieldNumber, int value) throws IOException;
+
+ /** Write a {@code sint32} field, including tag, to the stream. */
+ public final void writeSInt32(final int fieldNumber, final int value) throws IOException {
+ writeUInt32(fieldNumber, encodeZigZag32(value));
+ }
+
+ /** Write a {@code fixed32} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed32(int fieldNumber, int value) throws IOException;
+
+ /** Write an {@code sfixed32} field, including tag, to the stream. */
+ public final void writeSFixed32(final int fieldNumber, final int value) throws IOException {
+ writeFixed32(fieldNumber, value);
+ }
+
+ /** Write an {@code int64} field, including tag, to the stream. */
+ public final void writeInt64(final int fieldNumber, final long value) throws IOException {
+ writeUInt64(fieldNumber, value);
+ }
+
+ /** Write a {@code uint64} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt64(int fieldNumber, long value) throws IOException;
+
+ /** Write an {@code sint64} field, including tag, to the stream. */
+ public final void writeSInt64(final int fieldNumber, final long value) throws IOException {
+ writeUInt64(fieldNumber, encodeZigZag64(value));
+ }
+
+ /** Write a {@code fixed64} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed64(int fieldNumber, long value) throws IOException;
+
+ /** Write an {@code sfixed64} field, including tag, to the stream. */
+ public final void writeSFixed64(final int fieldNumber, final long value) throws IOException {
+ writeFixed64(fieldNumber, value);
+ }
+
+ /** Write a {@code float} field, including tag, to the stream. */
+ public final void writeFloat(final int fieldNumber, final float value) throws IOException {
+ writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
+ }
+
+ /** Write a {@code double} field, including tag, to the stream. */
+ public final void writeDouble(final int fieldNumber, final double value) throws IOException {
+ writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
+ }
+
+ /** Write a {@code bool} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBool(int fieldNumber, boolean value) throws IOException;
+
+ /**
+ * Write an enum field, including tag, to the stream. The provided value is the numeric
+ * value used to represent the enum value on the wire (not the enum ordinal value).
+ */
+ public final void writeEnum(final int fieldNumber, final int value) throws IOException {
+ writeInt32(fieldNumber, value);
+ }
+
+ /** Write a {@code string} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeString(int fieldNumber, String value) throws IOException;
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException;
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException;
+
+ /** Write a {@code bytes} field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
+ throws IOException;
+
+ /**
+ * Write a {@code bytes} field, including tag, to the stream.
+ * This method will write all content of the ByteBuffer regardless of the
+ * current position and limit (i.e., the number of bytes to be written is
+ * value.capacity(), not value.remaining()). Furthermore, this method doesn't
+ * alter the state of the passed-in ByteBuffer. Its position, limit, mark,
+ * etc. will remain unchanged. If you only want to write the remaining bytes
+ * of a ByteBuffer, you can call
+ * {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}.
+ */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException;
+
+ /**
+ * Write a single byte.
+ */
+ public final void writeRawByte(final byte value) throws IOException {
+ write(value);
+ }
+
+ /** Write a single byte, represented by an integer value. */
+ public final void writeRawByte(final int value) throws IOException {
+ write((byte) value);
+ }
+
+ /** Write an array of bytes. */
+ public final void writeRawBytes(final byte[] value) throws IOException {
+ write(value, 0, value.length);
+ }
+
+ /**
+ * Write part of an array of bytes.
+ */
+ public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ /** Write a byte string. */
+ public final void writeRawBytes(final ByteString value) throws IOException {
+ value.writeTo(this);
+ }
+
+ /**
+ * Write a ByteBuffer. This method will write all content of the ByteBuffer
+ * regardless of the current position and limit (i.e., the number of bytes
+ * to be written is value.capacity(), not value.remaining()). Furthermore,
+ * this method doesn't alter the state of the passed-in ByteBuffer. Its
+ * position, limit, mark, etc. will remain unchanged. If you only want to
+ * write the remaining bytes of a ByteBuffer, you can call
+ * {@code writeRawBytes(byteBuffer.slice())}.
+ */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeRawBytes(final ByteBuffer value) throws IOException;
+
+ /** Write an embedded message field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException;
+
+ /**
+ * Write a MessageSet extension field to the stream. For historical reasons,
+ * the wire format differs from normal fields.
+ */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException;
+
+ /**
+ * Write an unparsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException;
+
+ // -----------------------------------------------------------------
+
+ /** Write an {@code int32} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeInt32NoTag(final int value) throws IOException;
+
+ /** Write a {@code uint32} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt32NoTag(int value) throws IOException;
+
+ /** Write a {@code sint32} field to the stream. */
+ public final void writeSInt32NoTag(final int value) throws IOException {
+ writeUInt32NoTag(encodeZigZag32(value));
+ }
+
+ /** Write a {@code fixed32} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed32NoTag(int value) throws IOException;
+
+ /** Write a {@code sfixed32} field to the stream. */
+ public final void writeSFixed32NoTag(final int value) throws IOException {
+ writeFixed32NoTag(value);
+ }
+
+ /** Write an {@code int64} field to the stream. */
+ public final void writeInt64NoTag(final long value) throws IOException {
+ writeUInt64NoTag(value);
+ }
+
+ /** Write a {@code uint64} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt64NoTag(long value) throws IOException;
+
+ /** Write a {@code sint64} field to the stream. */
+ public final void writeSInt64NoTag(final long value) throws IOException {
+ writeUInt64NoTag(encodeZigZag64(value));
+ }
+
+ /** Write a {@code fixed64} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed64NoTag(long value) throws IOException;
+
+ /** Write a {@code sfixed64} field to the stream. */
+ public final void writeSFixed64NoTag(final long value) throws IOException {
+ writeFixed64NoTag(value);
+ }
+
+ /** Write a {@code float} field to the stream. */
+ public final void writeFloatNoTag(final float value) throws IOException {
+ writeFixed32NoTag(Float.floatToRawIntBits(value));
+ }
+
+ /** Write a {@code double} field to the stream. */
+ public final void writeDoubleNoTag(final double value) throws IOException {
+ writeFixed64NoTag(Double.doubleToRawLongBits(value));
+ }
+
+ /** Write a {@code bool} field to the stream. */
+ public final void writeBoolNoTag(final boolean value) throws IOException {
+ write((byte) (value ? 1 : 0));
+ }
+
+ /**
+ * Write an enum field to the stream. The provided value is the numeric
+ * value used to represent the enum value on the wire (not the enum ordinal value).
+ */
+ public final void writeEnumNoTag(final int value) throws IOException {
+ writeInt32NoTag(value);
+ }
+
+ /** Write a {@code string} field to the stream. */
+ // TODO(dweis): Document behavior on ill-formed UTF-16 input.
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeStringNoTag(String value) throws IOException;
+
+ /** Write a {@code bytes} field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBytesNoTag(final ByteString value) throws IOException;
+
+ /** Write a {@code bytes} field to the stream. */
+ public final void writeByteArrayNoTag(final byte[] value) throws IOException {
+ writeByteArrayNoTag(value, 0, value.length);
+ }
+
+ /** Write an embedded message field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
+
+ //=================================================================
+
+ @ExperimentalApi
+ @Override
+ public abstract void write(byte value) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void write(byte[] value, int offset, int length) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
+
+ @Override
+ public abstract void write(ByteBuffer value) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void writeLazy(ByteBuffer value) throws IOException;
+
+ // =================================================================
+ // =================================================================
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int32} field, including tag.
+ */
+ public static int computeInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint32} field, including tag.
+ */
+ public static int computeUInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint32} field, including tag.
+ */
+ public static int computeSInt32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed32} field, including tag.
+ */
+ public static int computeFixed32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed32} field, including tag.
+ */
+ public static int computeSFixed32Size(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int64} field, including tag.
+ */
+ public static int computeInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint64} field, including tag.
+ */
+ public static int computeUInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint64} field, including tag.
+ */
+ public static int computeSInt64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed64} field, including tag.
+ */
+ public static int computeFixed64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed64} field, including tag.
+ */
+ public static int computeSFixed64Size(final int fieldNumber, final long value) {
+ return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code float} field, including tag.
+ */
+ public static int computeFloatSize(final int fieldNumber, final float value) {
+ return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code double} field, including tag.
+ */
+ public static int computeDoubleSize(final int fieldNumber, final double value) {
+ return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bool} field, including tag.
+ */
+ public static int computeBoolSize(final int fieldNumber, final boolean value) {
+ return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * enum field, including tag. The provided value is the numeric
+ * value used to represent the enum value on the wire (not the enum ordinal value).
+ */
+ public static int computeEnumSize(final int fieldNumber, final int value) {
+ return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code string} field, including tag.
+ */
+ public static int computeStringSize(final int fieldNumber, final String value) {
+ return computeTagSize(fieldNumber) + computeStringSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field, including tag.
+ */
+ public static int computeBytesSize(final int fieldNumber, final ByteString value) {
+ return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field, including tag.
+ */
+ public static int computeByteArraySize(final int fieldNumber, final byte[] value) {
+ return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field, including tag.
+ */
+ public static int computeByteBufferSize(final int fieldNumber, final ByteBuffer value) {
+ return computeTagSize(fieldNumber) + computeByteBufferSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * embedded message in lazy field, including tag.
+ */
+ public static int computeLazyFieldSize(final int fieldNumber, final LazyFieldLite value) {
+ return computeTagSize(fieldNumber) + computeLazyFieldSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * embedded message field, including tag.
+ */
+ public static int computeMessageSize(final int fieldNumber, final MessageLite value) {
+ return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * MessageSet extension to the stream. For historical reasons,
+ * the wire format differs from normal fields.
+ */
+ public static int computeMessageSetExtensionSize(final int fieldNumber, final MessageLite value) {
+ return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+ + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+ + computeMessageSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * unparsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+ public static int computeRawMessageSetExtensionSize(
+ final int fieldNumber, final ByteString value) {
+ return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+ + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+ + computeBytesSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * lazily parsed MessageSet extension field to the stream. For
+ * historical reasons, the wire format differs from normal fields.
+ */
+ public static int computeLazyFieldMessageSetExtensionSize(
+ final int fieldNumber, final LazyFieldLite value) {
+ return computeTagSize(WireFormat.MESSAGE_SET_ITEM) * 2
+ + computeUInt32Size(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber)
+ + computeLazyFieldSize(WireFormat.MESSAGE_SET_MESSAGE, value);
+ }
+
+ // -----------------------------------------------------------------
+
+ /** Compute the number of bytes that would be needed to encode a tag. */
+ public static int computeTagSize(final int fieldNumber) {
+ return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int32} field, including tag.
+ */
+ public static int computeInt32SizeNoTag(final int value) {
+ if (value >= 0) {
+ return computeUInt32SizeNoTag(value);
+ } else {
+ // Must sign-extend.
+ return MAX_VARINT_SIZE;
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint32} field.
+ */
+ public static int computeUInt32SizeNoTag(final int value) {
+ if ((value & (~0 << 7)) == 0) {
+ return 1;
+ }
+ if ((value & (~0 << 14)) == 0) {
+ return 2;
+ }
+ if ((value & (~0 << 21)) == 0) {
+ return 3;
+ }
+ if ((value & (~0 << 28)) == 0) {
+ return 4;
+ }
+ return 5;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint32} field.
+ */
+ public static int computeSInt32SizeNoTag(final int value) {
+ return computeUInt32SizeNoTag(encodeZigZag32(value));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed32} field.
+ */
+ public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
+ return FIXED_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed32} field.
+ */
+ public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
+ return FIXED_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code int64} field, including tag.
+ */
+ public static int computeInt64SizeNoTag(final long value) {
+ return computeUInt64SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code uint64} field, including tag.
+ */
+ public static int computeUInt64SizeNoTag(long value) {
+ // handle two popular special cases up front ...
+ if ((value & (~0L << 7)) == 0L) {
+ return 1;
+ }
+ if (value < 0L) {
+ return 10;
+ }
+ // ... leaving us with 8 remaining, which we can divide and conquer
+ int n = 2;
+ if ((value & (~0L << 35)) != 0L) {
+ n += 4; value >>>= 28;
+ }
+ if ((value & (~0L << 21)) != 0L) {
+ n += 2; value >>>= 14;
+ }
+ if ((value & (~0L << 14)) != 0L) {
+ n += 1;
+ }
+ return n;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sint64} field.
+ */
+ public static int computeSInt64SizeNoTag(final long value) {
+ return computeUInt64SizeNoTag(encodeZigZag64(value));
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code fixed64} field.
+ */
+ public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
+ return FIXED_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an
+ * {@code sfixed64} field.
+ */
+ public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
+ return FIXED_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code float} field, including tag.
+ */
+ public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
+ return FIXED_32_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code double} field, including tag.
+ */
+ public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
+ return FIXED_64_SIZE;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bool} field.
+ */
+ public static int computeBoolSizeNoTag(@SuppressWarnings("unused") final boolean unused) {
+ return 1;
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an enum field.
+ * The provided value is the numeric value used to represent the enum value on the wire
+ * (not the enum ordinal value).
+ */
+ public static int computeEnumSizeNoTag(final int value) {
+ return computeInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code string} field.
+ */
+ public static int computeStringSizeNoTag(final String value) {
+ int length;
+ try {
+ length = Utf8.encodedLength(value);
+ } catch (UnpairedSurrogateException e) {
+ // TODO(dweis): Consider using nio Charset methods instead.
+ final byte[] bytes = value.getBytes(Internal.UTF_8);
+ length = bytes.length;
+ }
+
+ return computeLengthDelimitedFieldSize(length);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message stored in lazy field.
+ */
+ public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
+ return computeLengthDelimitedFieldSize(value.getSerializedSize());
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeBytesSizeNoTag(final ByteString value) {
+ return computeLengthDelimitedFieldSize(value.size());
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeByteArraySizeNoTag(final byte[] value) {
+ return computeLengthDelimitedFieldSize(value.length);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code bytes} field.
+ */
+ public static int computeByteBufferSizeNoTag(final ByteBuffer value) {
+ return computeLengthDelimitedFieldSize(value.capacity());
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded
+ * message field.
+ */
+ public static int computeMessageSizeNoTag(final MessageLite value) {
+ return computeLengthDelimitedFieldSize(value.getSerializedSize());
+ }
+
+ static int computeLengthDelimitedFieldSize(int fieldLength) {
+ return computeUInt32SizeNoTag(fieldLength) + fieldLength;
+ }
+
+ /**
+ * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n A signed 32-bit integer.
+ * @return An unsigned 32-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ */
+ public static int encodeZigZag32(final int n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 31);
+ }
+
+ /**
+ * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
+ * into values that can be efficiently encoded with varint. (Otherwise,
+ * negative values must be sign-extended to 64 bits to be varint encoded,
+ * thus always taking 10 bytes on the wire.)
+ *
+ * @param n A signed 64-bit integer.
+ * @return An unsigned 64-bit integer, stored in a signed int because
+ * Java has no explicit unsigned support.
+ */
+ public static long encodeZigZag64(final long n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 63);
+ }
+
+ // =================================================================
+
+ /**
+ * Flushes the stream and forces any buffered bytes to be written. This
+ * does not flush the underlying OutputStream.
+ */
+ public abstract void flush() throws IOException;
+
+ /**
+ * If writing to a flat array, return the space left in the array.
+ * Otherwise, throws {@code UnsupportedOperationException}.
+ */
+ public abstract int spaceLeft();
+
+ /**
+ * Verifies that {@link #spaceLeft()} returns zero. It's common to create
+ * a byte array that is exactly big enough to hold a message, then write to
+ * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()}
+ * after writing verifies that the message was actually as big as expected,
+ * which can help catch bugs.
+ */
+ public final void checkNoSpaceLeft() {
+ if (spaceLeft() != 0) {
+ throw new IllegalStateException("Did not write as much data as expected.");
+ }
+ }
+
+ /**
+ * If you create a CodedOutputStream around a simple flat array, you must
+ * not attempt to write more bytes than the array has space. Otherwise,
+ * this exception will be thrown.
+ */
+ public static class OutOfSpaceException extends IOException {
+ private static final long serialVersionUID = -6947486886997889499L;
+
+ private static final String MESSAGE =
+ "CodedOutputStream was writing to a flat byte array and ran out of space.";
+
+ OutOfSpaceException() {
+ super(MESSAGE);
+ }
+
+ OutOfSpaceException(String explanationMessage) {
+ super(MESSAGE + ": " + explanationMessage);
+ }
+
+ OutOfSpaceException(Throwable cause) {
+ super(MESSAGE, cause);
+ }
+
+ OutOfSpaceException(String explanationMessage, Throwable cause) {
+ super(MESSAGE + ": " + explanationMessage, cause);
+ }
+ }
+
+ /**
+ * Get the total number of bytes successfully written to this stream. The
+ * returned value is not guaranteed to be accurate if exceptions have been
+ * found in the middle of writing.
+ */
+ public abstract int getTotalBytesWritten();
+
+ // =================================================================
+
+ /** Write a {@code bytes} field to the stream. Visible for testing. */
+ abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
+ throws IOException;
+
+ final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause)
+ throws IOException {
+ logger.log(Level.WARNING,
+ "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause);
+
+ // Unfortunately there does not appear to be any way to tell Java to encode
+ // UTF-8 directly into our buffer, so we have to let it create its own byte
+ // array and then copy.
+ // TODO(dweis): Consider using nio Charset methods instead.
+ final byte[] bytes = value.getBytes(Internal.UTF_8);
+ try {
+ writeUInt32NoTag(bytes.length);
+ writeLazy(bytes, 0, bytes.length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ } catch (OutOfSpaceException e) {
+ throw e;
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Write a {@code group} field, including tag, to the stream.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ writeGroupNoTag(value);
+ writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ /**
+ * Write a {@code group} field to the stream.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ public final void writeGroupNoTag(final MessageLite value) throws IOException {
+ value.writeTo(this);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field, including tag.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ public static int computeGroupSize(final int fieldNumber, final MessageLite value) {
+ return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * {@code group} field.
+ */
+ @Deprecated
+ public static int computeGroupSizeNoTag(final MessageLite value) {
+ return value.getSerializedSize();
+ }
+
+ /**
+ * Encode and write a varint. {@code value} is treated as
+ * unsigned, so it won't be sign-extended if negative.
+ *
+ * @deprecated use {@link #writeUInt32NoTag} instead.
+ */
+ @Deprecated
+ public final void writeRawVarint32(int value) throws IOException {
+ writeUInt32NoTag(value);
+ }
+
+ /**
+ * Encode and write a varint.
+ *
+ * @deprecated use {@link #writeUInt64NoTag} instead.
+ */
+ @Deprecated
+ public final void writeRawVarint64(long value) throws IOException {
+ writeUInt64NoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a varint.
+ * {@code value} is treated as unsigned, so it won't be sign-extended if
+ * negative.
+ *
+ * @deprecated use {@link #computeUInt32SizeNoTag(int)} instead.
+ */
+ @Deprecated
+ public static int computeRawVarint32Size(final int value) {
+ return computeUInt32SizeNoTag(value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a varint.
+ *
+ * @deprecated use {@link #computeUInt64SizeNoTag(long)} instead.
+ */
+ @Deprecated
+ public static int computeRawVarint64Size(long value) {
+ return computeUInt64SizeNoTag(value);
+ }
+
+ /**
+ * Write a little-endian 32-bit integer.
+ *
+ * @deprecated Use {@link #writeFixed32NoTag} instead.
+ */
+ @Deprecated
+ public final void writeRawLittleEndian32(final int value) throws IOException {
+ writeFixed32NoTag(value);
+ }
+
+ /**
+ * Write a little-endian 64-bit integer.
+ *
+ * @deprecated Use {@link #writeFixed64NoTag} instead.
+ */
+ @Deprecated
+ public final void writeRawLittleEndian64(final long value) throws IOException {
+ writeFixed64NoTag(value);
+ }
+
+ // =================================================================
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a byte array.
+ */
+ private static class ArrayEncoder extends CodedOutputStream {
+ private final byte[] buffer;
+ private final int offset;
+ private final int limit;
+ private int position;
+
+ ArrayEncoder(byte[] buffer, int offset, int length) {
+ if (buffer == null) {
+ throw new NullPointerException("buffer");
+ }
+ if ((offset | length | (buffer.length - (offset + length))) < 0) {
+ throw new IllegalArgumentException(String.format(
+ "Array range is invalid. Buffer.length=%d, offset=%d, length=%d",
+ buffer.length, offset, length));
+ }
+ this.buffer = buffer;
+ this.offset = offset;
+ position = offset;
+ limit = offset + length;
+ }
+
+ @Override
+ public final void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public final void writeInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ @Override
+ public final void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ @Override
+ public final void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ @Override
+ public final void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ @Override
+ public final void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ @Override
+ public final void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public final void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public final void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public final void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public final void writeByteArrayNoTag(final byte[] value, int offset, int length)
+ throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public final void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public final void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public final void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public final void write(byte value) throws IOException {
+ try {
+ buffer[position++] = value;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ }
+ }
+
+ @Override
+ public final void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public final void writeUInt32NoTag(int value) throws IOException {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+ long pos = ARRAY_BASE_OFFSET + position;
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ position++;
+ return;
+ } else {
+ UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ position++;
+ value >>>= 7;
+ }
+ }
+ } else {
+ try {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer[position++] = (byte) value;
+ return;
+ } else {
+ buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed32NoTag(int value) throws IOException {
+ try {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ }
+ }
+
+ @Override
+ public final void writeUInt64NoTag(long value) throws IOException {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+ long pos = ARRAY_BASE_OFFSET + position;
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ position++;
+ return;
+ } else {
+ UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ position++;
+ value >>>= 7;
+ }
+ }
+ } else {
+ try {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer[position++] = (byte) value;
+ return;
+ } else {
+ buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed64NoTag(long value) throws IOException {
+ try {
+ buffer[position++] = (byte) ((int) (value) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
+ }
+ }
+
+ @Override
+ public final void write(byte[] value, int offset, int length) throws IOException {
+ try {
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
+ }
+ }
+
+ @Override
+ public final void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public final void write(ByteBuffer value) throws IOException {
+ final int length = value.remaining();
+ try {
+ value.get(buffer, position, length);
+ position += length;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length), e);
+ }
+ }
+
+ @Override
+ public final void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ @Override
+ public final void writeStringNoTag(String value) throws IOException {
+ final int oldPosition = position;
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, spaceLeft());
+ // Since this class is stateful and tracks the position, we rewind and store the state,
+ // prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ int length = newPosition - oldPosition - minLengthVarIntSize;
+ writeUInt32NoTag(length);
+ position = newPosition;
+ } else {
+ int length = Utf8.encodedLength(value);
+ writeUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, spaceLeft());
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change - we fall back to inefficient path.
+ position = oldPosition;
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Do nothing.
+ }
+
+ @Override
+ public final int spaceLeft() {
+ return limit - position;
+ }
+
+ @Override
+ public final int getTotalBytesWritten() {
+ return position - offset;
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are
+ * done directly to the underlying array. The buffer position is only updated after a flush.
+ */
+ private static final class HeapNioEncoder extends ArrayEncoder {
+ private final ByteBuffer byteBuffer;
+ private int initialPosition;
+
+ HeapNioEncoder(ByteBuffer byteBuffer) {
+ super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(),
+ byteBuffer.remaining());
+ this.byteBuffer = byteBuffer;
+ this.initialPosition = byteBuffer.position();
+ }
+
+ @Override
+ public void flush() {
+ // Update the position on the buffer.
+ byteBuffer.position(initialPosition + getTotalBytesWritten());
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuffer}, using only
+ * safe operations..
+ */
+ private static final class SafeDirectNioEncoder extends CodedOutputStream {
+ private final ByteBuffer originalBuffer;
+ private final ByteBuffer buffer;
+ private final int initialPosition;
+
+ SafeDirectNioEncoder(ByteBuffer buffer) {
+ this.originalBuffer = buffer;
+ this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+ initialPosition = buffer.position();
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ try {
+ buffer.put(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ try {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer.put((byte) value);
+ return;
+ } else {
+ buffer.put((byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeFixed32NoTag(int value) throws IOException {
+ try {
+ buffer.putInt(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ try {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer.put((byte) value);
+ return;
+ } else {
+ buffer.put((byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeFixed64NoTag(long value) throws IOException {
+ try {
+ buffer.putLong(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ try {
+ buffer.put(value, offset, length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ try {
+ buffer.put(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ final int startPos = buffer.position();
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ // Save the current position and increment past the length field. We'll come back
+ // and write the length field after the encoding is complete.
+ final int startOfBytes = buffer.position() + minLengthVarIntSize;
+ buffer.position(startOfBytes);
+
+ // Encode the string.
+ encode(value);
+
+ // Now go back to the beginning and write the length.
+ int endOfBytes = buffer.position();
+ buffer.position(startPos);
+ writeUInt32NoTag(endOfBytes - startOfBytes);
+
+ // Reposition the buffer past the written data.
+ buffer.position(endOfBytes);
+ } else {
+ final int length = Utf8.encodedLength(value);
+ writeUInt32NoTag(length);
+ encode(value);
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change and convert to an IOException.
+ buffer.position(startPos);
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IllegalArgumentException e) {
+ // Thrown by buffer.position() if out of range.
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Update the position of the original buffer.
+ originalBuffer.position(buffer.position());
+ }
+
+ @Override
+ public int spaceLeft() {
+ return buffer.remaining();
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return buffer.position() - initialPosition;
+ }
+
+ private void encode(String value) throws IOException {
+ try {
+ Utf8.encodeUtf8(value, buffer);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuffer} using {@code
+ * sun.misc.Unsafe}.
+ */
+ private static final class UnsafeDirectNioEncoder extends CodedOutputStream {
+ private final ByteBuffer originalBuffer;
+ private final ByteBuffer buffer;
+ private final long address;
+ private final long initialPosition;
+ private final long limit;
+ private final long oneVarintLimit;
+ private long position;
+
+ UnsafeDirectNioEncoder(ByteBuffer buffer) {
+ this.originalBuffer = buffer;
+ this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+ address = UnsafeUtil.addressOffset(buffer);
+ initialPosition = address + buffer.position();
+ limit = address + buffer.limit();
+ oneVarintLimit = limit - MAX_VARINT_SIZE;
+ position = initialPosition;
+ }
+
+ static boolean isSupported() {
+ return UnsafeUtil.hasUnsafeByteBufferOperations();
+ }
+
+ @Override
+ public void writeTag(int fieldNumber, int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(int fieldNumber, byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, MessageLite value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(int fieldNumber, MessageLite value) throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(int fieldNumber, ByteString value) throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ if (position >= limit) {
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
+ }
+ UnsafeUtil.putByte(position++, value);
+ }
+
+ @Override
+ public void writeBytesNoTag(ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ if (position <= oneVarintLimit) {
+ // Optimization to avoid bounds checks on each iteration.
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ UnsafeUtil.putByte(position++, (byte) value);
+ return;
+ } else {
+ UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } else {
+ while (position < limit) {
+ if ((value & ~0x7F) == 0) {
+ UnsafeUtil.putByte(position++, (byte) value);
+ return;
+ } else {
+ UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
+ }
+ }
+
+ @Override
+ public void writeFixed32NoTag(int value) throws IOException {
+ buffer.putInt(bufferPos(position), value);
+ position += FIXED_32_SIZE;
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ if (position <= oneVarintLimit) {
+ // Optimization to avoid bounds checks on each iteration.
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ UnsafeUtil.putByte(position++, (byte) value);
+ return;
+ } else {
+ UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } else {
+ while (position < limit) {
+ if ((value & ~0x7FL) == 0) {
+ UnsafeUtil.putByte(position++, (byte) value);
+ return;
+ } else {
+ UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
+ }
+ }
+
+ @Override
+ public void writeFixed64NoTag(long value) throws IOException {
+ buffer.putLong(bufferPos(position), value);
+ position += FIXED_64_SIZE;
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ if (value == null
+ || offset < 0
+ || length < 0
+ || (value.length - length) < offset
+ || (limit - length) < position) {
+ if (value == null) {
+ throw new NullPointerException("value");
+ }
+ throw new OutOfSpaceException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length));
+ }
+
+ UnsafeUtil.copyMemory(
+ value, UnsafeUtil.getArrayBaseOffset() + offset, null, position, length);
+ position += length;
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ try {
+ int length = value.remaining();
+ repositionBuffer(position);
+ buffer.put(value);
+ position += length;
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ long prevPos = position;
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
+ int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ // Save the current position and increment past the length field. We'll come back
+ // and write the length field after the encoding is complete.
+ int stringStart = bufferPos(position) + minLengthVarIntSize;
+ buffer.position(stringStart);
+
+ // Encode the string.
+ Utf8.encodeUtf8(value, buffer);
+
+ // Write the length and advance the position.
+ int length = buffer.position() - stringStart;
+ writeUInt32NoTag(length);
+ position += length;
+ } else {
+ // Calculate and write the encoded length.
+ int length = Utf8.encodedLength(value);
+ writeUInt32NoTag(length);
+
+ // Write the string and advance the position.
+ repositionBuffer(position);
+ Utf8.encodeUtf8(value, buffer);
+ position += length;
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change and convert to an IOException.
+ position = prevPos;
+ repositionBuffer(position);
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IllegalArgumentException e) {
+ // Thrown by buffer.position() if out of range.
+ throw new OutOfSpaceException(e);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Update the position of the original buffer.
+ originalBuffer.position(bufferPos(position));
+ }
+
+ @Override
+ public int spaceLeft() {
+ return (int) (limit - position);
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return (int) (position - initialPosition);
+ }
+
+ private void repositionBuffer(long pos) {
+ buffer.position(bufferPos(pos));
+ }
+
+ private int bufferPos(long pos) {
+ return (int) (pos - address);
+ }
+ }
+
+ /**
+ * Abstract base class for buffered encoders.
+ */
+ private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
+ final byte[] buffer;
+ final int limit;
+ int position;
+ int totalBytesWritten;
+
+ AbstractBufferedEncoder(int bufferSize) {
+ if (bufferSize < 0) {
+ throw new IllegalArgumentException("bufferSize must be >= 0");
+ }
+ // As an optimization, we require that the buffer be able to store at least 2
+ // varints so that we can buffer any integer write (tag + value). This reduces the
+ // number of range checks for a single write to 1 (i.e. if there is not enough space
+ // to buffer the tag+value, flush and then buffer it).
+ this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)];
+ this.limit = buffer.length;
+ }
+
+ @Override
+ public final int spaceLeft() {
+ throw new UnsupportedOperationException(
+ "spaceLeft() can only be called on CodedOutputStreams that are "
+ + "writing to a flat array or ByteBuffer.");
+ }
+
+ @Override
+ public final int getTotalBytesWritten() {
+ return totalBytesWritten;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void buffer(byte value) {
+ buffer[position++] = value;
+ totalBytesWritten++;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferTag(final int fieldNumber, final int wireType) {
+ bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferInt32NoTag(final int value) {
+ if (value >= 0) {
+ bufferUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ bufferUInt64NoTag(value);
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferUInt32NoTag(int value) {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+ final long originalPos = ARRAY_BASE_OFFSET + position;
+ long pos = originalPos;
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ break;
+ } else {
+ UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ int delta = (int) (pos - originalPos);
+ position += delta;
+ totalBytesWritten += delta;
+ } else {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer[position++] = (byte) value;
+ totalBytesWritten++;
+ return;
+ } else {
+ buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+ totalBytesWritten++;
+ value >>>= 7;
+ }
+ }
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferUInt64NoTag(long value) {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+ final long originalPos = ARRAY_BASE_OFFSET + position;
+ long pos = originalPos;
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ UnsafeUtil.putByte(buffer, pos++, (byte) value);
+ break;
+ } else {
+ UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ int delta = (int) (pos - originalPos);
+ position += delta;
+ totalBytesWritten += delta;
+ } else {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer[position++] = (byte) value;
+ totalBytesWritten++;
+ return;
+ } else {
+ buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+ totalBytesWritten++;
+ value >>>= 7;
+ }
+ }
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferFixed32NoTag(int value) {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ totalBytesWritten += FIXED_32_SIZE;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferFixed64NoTag(long value) {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+ totalBytesWritten += FIXED_64_SIZE;
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to
+ * support string encoding operations. All other writes are just passed through to the
+ * {@link ByteOutput}.
+ */
+ private static final class ByteOutputEncoder extends AbstractBufferedEncoder {
+ private final ByteOutput out;
+
+ ByteOutputEncoder(ByteOutput out, int bufferSize) {
+ super(bufferSize);
+ if (out == null) {
+ throw new NullPointerException("out");
+ }
+ this.out = out;
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ buffer((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ if (position == limit) {
+ doFlush();
+ }
+
+ buffer(value);
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32NoTag(final int value) throws IOException {
+ flushIfNotAvailable(FIXED_32_SIZE);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64NoTag(final long value) throws IOException {
+ flushIfNotAvailable(FIXED_64_SIZE);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+ // If we are streaming and the potential length is too big to fit in our buffer, we take the
+ // slower path.
+ if (maxLengthVarIntSize + maxLength > limit) {
+ // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+ // does the same internally and then does *another copy* to return a byte[] of exactly the
+ // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+ // UTF-8 encoded bytes.
+ final byte[] encodedBytes = new byte[maxLength];
+ int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+ writeUInt32NoTag(actualLength);
+ writeLazy(encodedBytes, 0, actualLength);
+ return;
+ }
+
+ // Fast path: we have enough space available in our buffer for the string...
+ if (maxLengthVarIntSize + maxLength > limit - position) {
+ // Flush to free up space.
+ doFlush();
+ }
+
+ final int oldPosition = position;
+ try {
+ // Optimize for the case where we know this length results in a constant varint length as
+ // this saves a pass for measuring the length of the string.
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, limit - position);
+ // Since this class is stateful and tracks the position, we rewind and store the state,
+ // prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ int length = newPosition - oldPosition - minLengthVarIntSize;
+ bufferUInt32NoTag(length);
+ position = newPosition;
+ totalBytesWritten += length;
+ } else {
+ int length = Utf8.encodedLength(value);
+ bufferUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, length);
+ totalBytesWritten += length;
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change and convert to an IOException.
+ totalBytesWritten -= position - oldPosition;
+ position = oldPosition;
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (position > 0) {
+ // Flush the buffer.
+ doFlush();
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ flush();
+ out.write(value, offset, length);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ flush();
+ out.writeLazy(value, offset, length);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ flush();
+ int length = value.remaining();
+ out.write(value);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ flush();
+ int length = value.remaining();
+ out.writeLazy(value);
+ totalBytesWritten += length;
+ }
+
+ private void flushIfNotAvailable(int requiredSize) throws IOException {
+ if (limit - position < requiredSize) {
+ doFlush();
+ }
+ }
+
+ private void doFlush() throws IOException {
+ out.write(buffer, 0, position);
+ position = 0;
+ }
+ }
+
+ /**
+ * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal
+ * buffering to optimize writes to the {@link OutputStream}.
+ */
+ private static final class OutputStreamEncoder extends AbstractBufferedEncoder {
+ private final OutputStream out;
+
+ OutputStreamEncoder(OutputStream out, int bufferSize) {
+ super(bufferSize);
+ if (out == null) {
+ throw new NullPointerException("out");
+ }
+ this.out = out;
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ buffer((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ if (position == limit) {
+ doFlush();
+ }
+
+ buffer(value);
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32NoTag(final int value) throws IOException {
+ flushIfNotAvailable(FIXED_32_SIZE);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64NoTag(final long value) throws IOException {
+ flushIfNotAvailable(FIXED_64_SIZE);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+ // If we are streaming and the potential length is too big to fit in our buffer, we take the
+ // slower path.
+ if (maxLengthVarIntSize + maxLength > limit) {
+ // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+ // does the same internally and then does *another copy* to return a byte[] of exactly the
+ // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+ // UTF-8 encoded bytes.
+ final byte[] encodedBytes = new byte[maxLength];
+ int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+ writeUInt32NoTag(actualLength);
+ writeLazy(encodedBytes, 0, actualLength);
+ return;
+ }
+
+ // Fast path: we have enough space available in our buffer for the string...
+ if (maxLengthVarIntSize + maxLength > limit - position) {
+ // Flush to free up space.
+ doFlush();
+ }
+
+ // Optimize for the case where we know this length results in a constant varint length as
+ // this saves a pass for measuring the length of the string.
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ int oldPosition = position;
+ final int length;
+ try {
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, limit - position);
+ // Since this class is stateful and tracks the position, we rewind and store the
+ // state, prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ length = newPosition - oldPosition - minLengthVarIntSize;
+ bufferUInt32NoTag(length);
+ position = newPosition;
+ } else {
+ length = Utf8.encodedLength(value);
+ bufferUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, length);
+ }
+ totalBytesWritten += length;
+ } catch (UnpairedSurrogateException e) {
+ // Be extra careful and restore the original position for retrying the write with the
+ // less efficient path.
+ totalBytesWritten -= position - oldPosition;
+ position = oldPosition;
+ throw e;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ } catch (UnpairedSurrogateException e) {
+ inefficientWriteStringNoTag(value, e);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (position > 0) {
+ // Flush the buffer.
+ doFlush();
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length)
+ throws IOException {
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
+ totalBytesWritten += length;
+ } else {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ final int bytesWritten = limit - position;
+ System.arraycopy(value, offset, buffer, position, bytesWritten);
+ offset += bytesWritten;
+ length -= bytesWritten;
+ position = limit;
+ totalBytesWritten += bytesWritten;
+ doFlush();
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ if (length <= limit) {
+ // Fits in new buffer.
+ System.arraycopy(value, offset, buffer, 0, length);
+ position = length;
+ } else {
+ // Write is very big. Let's do it all at once.
+ out.write(value, offset, length);
+ }
+ totalBytesWritten += length;
+ }
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ int length = value.remaining();
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ value.get(buffer, position, length);
+ position += length;
+ totalBytesWritten += length;
+ } else {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ final int bytesWritten = limit - position;
+ value.get(buffer, position, bytesWritten);
+ length -= bytesWritten;
+ position = limit;
+ totalBytesWritten += bytesWritten;
+ doFlush();
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ while (length > limit) {
+ // Copy data into the buffer before writing it to OutputStream.
+ value.get(buffer, 0, limit);
+ out.write(buffer, 0, limit);
+ length -= limit;
+ totalBytesWritten += limit;
+ }
+ value.get(buffer, 0, length);
+ position = length;
+ totalBytesWritten += length;
+ }
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ private void flushIfNotAvailable(int requiredSize) throws IOException {
+ if (limit - position < requiredSize) {
+ doFlush();
+ }
+ }
+
+ private void doFlush() throws IOException {
+ out.write(buffer, 0, position);
+ position = 0;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Descriptors.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Descriptors.java
new file mode 100644
index 0000000000..38346f1559
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -0,0 +1,2547 @@
+// 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 com.google.protobuf.DescriptorProtos.*;
+import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.logging.Logger;
+
+/**
+ * Contains a collection of classes which describe protocol message types.
+ *
+ * Every message type has a {@link Descriptor}, which lists all
+ * its fields and other information about a type. You can get a message
+ * type's descriptor by calling {@code MessageType.getDescriptor()}, or
+ * (given a message object of the type) {@code message.getDescriptorForType()}.
+ * Furthermore, each message is associated with a {@link FileDescriptor} for
+ * a relevant {@code .proto} file. You can obtain it by calling
+ * {@code Descriptor.getFile()}. A {@link FileDescriptor} contains descriptors
+ * for all the messages defined in that file, and file descriptors for all the
+ * imported {@code .proto} files.
+ *
+ * Descriptors are built from DescriptorProtos, as defined in
+ * {@code google/protobuf/descriptor.proto}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class Descriptors {
+ private static final Logger logger =
+ Logger.getLogger(Descriptors.class.getName());
+ /**
+ * Describes a {@code .proto} file, including everything defined within.
+ * That includes, in particular, descriptors for all the messages and
+ * file descriptors for all other imported {@code .proto} files
+ * (dependencies).
+ */
+ public static final class FileDescriptor extends GenericDescriptor {
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public FileDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the file name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /** Returns this object. */
+ @Override
+ public FileDescriptor getFile() {
+ return this;
+ }
+
+ /** Returns the same as getName(). */
+ @Override
+ public String getFullName() {
+ return proto.getName();
+ }
+
+ /**
+ * Get the proto package name. This is the package name given by the
+ * {@code package} statement in the {@code .proto} file, which differs
+ * from the Java package.
+ */
+ public String getPackage() { return proto.getPackage(); }
+
+ /** Get the {@code FileOptions}, defined in {@code descriptor.proto}. */
+ public FileOptions getOptions() { return proto.getOptions(); }
+
+ /** Get a list of top-level message types declared in this file. */
+ public List<Descriptor> getMessageTypes() {
+ return Collections.unmodifiableList(Arrays.asList(messageTypes));
+ }
+
+ /** Get a list of top-level enum types declared in this file. */
+ public List<EnumDescriptor> getEnumTypes() {
+ return Collections.unmodifiableList(Arrays.asList(enumTypes));
+ }
+
+ /** Get a list of top-level services declared in this file. */
+ public List<ServiceDescriptor> getServices() {
+ return Collections.unmodifiableList(Arrays.asList(services));
+ }
+
+ /** Get a list of top-level extensions declared in this file. */
+ public List<FieldDescriptor> getExtensions() {
+ return Collections.unmodifiableList(Arrays.asList(extensions));
+ }
+
+ /** Get a list of this file's dependencies (imports). */
+ public List<FileDescriptor> getDependencies() {
+ return Collections.unmodifiableList(Arrays.asList(dependencies));
+ }
+
+ /** Get a list of this file's public dependencies (public imports). */
+ public List<FileDescriptor> getPublicDependencies() {
+ return Collections.unmodifiableList(Arrays.asList(publicDependencies));
+ }
+
+ /** The syntax of the .proto file. */
+ public enum Syntax {
+ UNKNOWN("unknown"),
+ PROTO2("proto2"),
+ PROTO3("proto3");
+
+ Syntax(String name) {
+ this.name = name;
+ }
+ private final String name;
+ }
+
+ /** Get the syntax of the .proto file. */
+ public Syntax getSyntax() {
+ if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
+ return Syntax.PROTO3;
+ }
+ return Syntax.PROTO2;
+ }
+
+ /**
+ * Find a message type in the file by name. Does not find nested types.
+ *
+ * @param name The unqualified type name to look for.
+ * @return The message type's descriptor, or {@code null} if not found.
+ */
+ public Descriptor findMessageTypeByName(String name) {
+ // Don't allow looking up nested types. This will make optimization
+ // easier later.
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
+ if (getPackage().length() > 0) {
+ name = getPackage() + '.' + name;
+ }
+ final GenericDescriptor result = pool.findSymbol(name);
+ if (result != null && result instanceof Descriptor &&
+ result.getFile() == this) {
+ return (Descriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Find an enum type in the file by name. Does not find nested types.
+ *
+ * @param name The unqualified type name to look for.
+ * @return The enum type's descriptor, or {@code null} if not found.
+ */
+ public EnumDescriptor findEnumTypeByName(String name) {
+ // Don't allow looking up nested types. This will make optimization
+ // easier later.
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
+ if (getPackage().length() > 0) {
+ name = getPackage() + '.' + name;
+ }
+ final GenericDescriptor result = pool.findSymbol(name);
+ if (result != null && result instanceof EnumDescriptor &&
+ result.getFile() == this) {
+ return (EnumDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Find a service type in the file by name.
+ *
+ * @param name The unqualified type name to look for.
+ * @return The service type's descriptor, or {@code null} if not found.
+ */
+ public ServiceDescriptor findServiceByName(String name) {
+ // Don't allow looking up nested types. This will make optimization
+ // easier later.
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
+ if (getPackage().length() > 0) {
+ name = getPackage() + '.' + name;
+ }
+ final GenericDescriptor result = pool.findSymbol(name);
+ if (result != null && result instanceof ServiceDescriptor &&
+ result.getFile() == this) {
+ return (ServiceDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Find an extension in the file by name. Does not find extensions nested
+ * inside message types.
+ *
+ * @param name The unqualified extension name to look for.
+ * @return The extension's descriptor, or {@code null} if not found.
+ */
+ public FieldDescriptor findExtensionByName(String name) {
+ if (name.indexOf('.') != -1) {
+ return null;
+ }
+ if (getPackage().length() > 0) {
+ name = getPackage() + '.' + name;
+ }
+ final GenericDescriptor result = pool.findSymbol(name);
+ if (result != null && result instanceof FieldDescriptor &&
+ result.getFile() == this) {
+ return (FieldDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Construct a {@code FileDescriptor}.
+ *
+ * @param proto The protocol message form of the FileDescriptor.
+ * @param dependencies {@code FileDescriptor}s corresponding to all of
+ * the file's dependencies.
+ * @throws DescriptorValidationException {@code proto} is not a valid
+ * descriptor. This can occur for a number of reasons, e.g.
+ * because a field has an undefined type or because two messages
+ * were defined with the same name.
+ */
+ public static FileDescriptor buildFrom(final FileDescriptorProto proto,
+ final FileDescriptor[] dependencies)
+ throws DescriptorValidationException {
+ return buildFrom(proto, dependencies, false);
+ }
+
+
+ /**
+ * Construct a {@code FileDescriptor}.
+ *
+ * @param proto The protocol message form of the FileDescriptor.
+ * @param dependencies {@code FileDescriptor}s corresponding to all of
+ * the file's dependencies.
+ * @param allowUnknownDependencies If true, non-exist dependenncies will be
+ * ignored and undefined message types will be replaced with a
+ * placeholder type.
+ * @throws DescriptorValidationException {@code proto} is not a valid
+ * descriptor. This can occur for a number of reasons, e.g.
+ * because a field has an undefined type or because two messages
+ * were defined with the same name.
+ */
+ public static FileDescriptor buildFrom(
+ final FileDescriptorProto proto, final FileDescriptor[] dependencies,
+ final boolean allowUnknownDependencies)
+ throws DescriptorValidationException {
+ // Building descriptors involves two steps: translating and linking.
+ // In the translation step (implemented by FileDescriptor's
+ // constructor), we build an object tree mirroring the
+ // FileDescriptorProto's tree and put all of the descriptors into the
+ // DescriptorPool's lookup tables. In the linking step, we look up all
+ // type references in the DescriptorPool, so that, for example, a
+ // FieldDescriptor for an embedded message contains a pointer directly
+ // to the Descriptor for that message's type. We also detect undefined
+ // types in the linking step.
+ final DescriptorPool pool = new DescriptorPool(
+ dependencies, allowUnknownDependencies);
+ final FileDescriptor result = new FileDescriptor(
+ proto, dependencies, pool, allowUnknownDependencies);
+ result.crossLink();
+ return result;
+ }
+
+ /**
+ * This method is to be called by generated code only. It is equivalent
+ * to {@code buildFrom} except that the {@code FileDescriptorProto} is
+ * encoded in protocol buffer wire format.
+ */
+ public static void internalBuildGeneratedFileFrom(
+ final String[] descriptorDataParts,
+ final FileDescriptor[] dependencies,
+ final InternalDescriptorAssigner descriptorAssigner) {
+ // Hack: We can't embed a raw byte array inside generated Java code
+ // (at least, not efficiently), but we can embed Strings. So, the
+ // protocol compiler embeds the FileDescriptorProto as a giant
+ // string literal which is passed to this function to construct the
+ // file's FileDescriptor. The string literal contains only 8-bit
+ // characters, each one representing a byte of the FileDescriptorProto's
+ // serialized form. So, if we convert it to bytes in ISO-8859-1, we
+ // should get the original bytes that we want.
+
+ // descriptorData may contain multiple strings in order to get around the
+ // Java 64k string literal limit.
+ StringBuilder descriptorData = new StringBuilder();
+ for (String part : descriptorDataParts) {
+ descriptorData.append(part);
+ }
+
+ final byte[] descriptorBytes;
+ descriptorBytes = descriptorData.toString().getBytes(Internal.ISO_8859_1);
+
+ FileDescriptorProto proto;
+ try {
+ proto = FileDescriptorProto.parseFrom(descriptorBytes);
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalArgumentException(
+ "Failed to parse protocol buffer descriptor for generated code.", e);
+ }
+
+ final FileDescriptor result;
+ try {
+ // When building descriptors for generated code, we allow unknown
+ // dependencies by default.
+ result = buildFrom(proto, dependencies, true);
+ } catch (DescriptorValidationException e) {
+ throw new IllegalArgumentException(
+ "Invalid embedded descriptor for \"" + proto.getName() + "\".", e);
+ }
+
+ final ExtensionRegistry registry =
+ descriptorAssigner.assignDescriptors(result);
+
+ if (registry != null) {
+ // We must re-parse the proto using the registry.
+ try {
+ proto = FileDescriptorProto.parseFrom(descriptorBytes, registry);
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalArgumentException(
+ "Failed to parse protocol buffer descriptor for generated code.",
+ e);
+ }
+
+ result.setProto(proto);
+ }
+ }
+
+ /**
+ * This method is to be called by generated code only. It uses Java
+ * reflection to load the dependencies' descriptors.
+ */
+ public static void internalBuildGeneratedFileFrom(
+ final String[] descriptorDataParts,
+ final Class<?> descriptorOuterClass,
+ final String[] dependencies,
+ final String[] dependencyFileNames,
+ final InternalDescriptorAssigner descriptorAssigner) {
+ List<FileDescriptor> descriptors = new ArrayList<FileDescriptor>();
+ for (int i = 0; i < dependencies.length; i++) {
+ try {
+ Class<?> clazz =
+ descriptorOuterClass.getClassLoader().loadClass(dependencies[i]);
+ descriptors.add(
+ (FileDescriptor) clazz.getField("descriptor").get(null));
+ } catch (Exception e) {
+ // We allow unknown dependencies by default. If a dependency cannot
+ // be found we only generate a warning.
+ logger.warning("Descriptors for \"" + dependencyFileNames[i] +
+ "\" can not be found.");
+ }
+ }
+ FileDescriptor[] descriptorArray = new FileDescriptor[descriptors.size()];
+ descriptors.toArray(descriptorArray);
+ internalBuildGeneratedFileFrom(
+ descriptorDataParts, descriptorArray, descriptorAssigner);
+ }
+
+ /**
+ * This method is to be called by generated code only. It is used to
+ * update the FileDescriptorProto associated with the descriptor by
+ * parsing it again with the given ExtensionRegistry. This is needed to
+ * recognize custom options.
+ */
+ public static void internalUpdateFileDescriptor(
+ final FileDescriptor descriptor,
+ final ExtensionRegistry registry) {
+ ByteString bytes = descriptor.proto.toByteString();
+ FileDescriptorProto proto;
+ try {
+ proto = FileDescriptorProto.parseFrom(bytes, registry);
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalArgumentException(
+ "Failed to parse protocol buffer descriptor for generated code.", e);
+ }
+ descriptor.setProto(proto);
+ }
+
+ /**
+ * This class should be used by generated code only. When calling
+ * {@link FileDescriptor#internalBuildGeneratedFileFrom}, the caller
+ * provides a callback implementing this interface. The callback is called
+ * after the FileDescriptor has been constructed, in order to assign all
+ * the global variables defined in the generated code which point at parts
+ * of the FileDescriptor. The callback returns an ExtensionRegistry which
+ * contains any extensions which might be used in the descriptor -- that
+ * is, extensions of the various "Options" messages defined in
+ * descriptor.proto. The callback may also return null to indicate that
+ * no extensions are used in the descriptor.
+ */
+ public interface InternalDescriptorAssigner {
+ ExtensionRegistry assignDescriptors(FileDescriptor root);
+ }
+
+ private FileDescriptorProto proto;
+ private final Descriptor[] messageTypes;
+ private final EnumDescriptor[] enumTypes;
+ private final ServiceDescriptor[] services;
+ private final FieldDescriptor[] extensions;
+ private final FileDescriptor[] dependencies;
+ private final FileDescriptor[] publicDependencies;
+ private final DescriptorPool pool;
+
+ private FileDescriptor(final FileDescriptorProto proto,
+ final FileDescriptor[] dependencies,
+ final DescriptorPool pool,
+ boolean allowUnknownDependencies)
+ throws DescriptorValidationException {
+ this.pool = pool;
+ this.proto = proto;
+ this.dependencies = dependencies.clone();
+ HashMap<String, FileDescriptor> nameToFileMap =
+ new HashMap<String, FileDescriptor>();
+ for (FileDescriptor file : dependencies) {
+ nameToFileMap.put(file.getName(), file);
+ }
+ List<FileDescriptor> publicDependencies = new ArrayList<FileDescriptor>();
+ for (int i = 0; i < proto.getPublicDependencyCount(); i++) {
+ int index = proto.getPublicDependency(i);
+ if (index < 0 || index >= proto.getDependencyCount()) {
+ throw new DescriptorValidationException(this,
+ "Invalid public dependency index.");
+ }
+ String name = proto.getDependency(index);
+ FileDescriptor file = nameToFileMap.get(name);
+ if (file == null) {
+ if (!allowUnknownDependencies) {
+ throw new DescriptorValidationException(this,
+ "Invalid public dependency: " + name);
+ }
+ // Ignore unknown dependencies.
+ } else {
+ publicDependencies.add(file);
+ }
+ }
+ this.publicDependencies = new FileDescriptor[publicDependencies.size()];
+ publicDependencies.toArray(this.publicDependencies);
+
+ pool.addPackage(getPackage(), this);
+
+ messageTypes = new Descriptor[proto.getMessageTypeCount()];
+ for (int i = 0; i < proto.getMessageTypeCount(); i++) {
+ messageTypes[i] =
+ new Descriptor(proto.getMessageType(i), this, null, i);
+ }
+
+ enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+ for (int i = 0; i < proto.getEnumTypeCount(); i++) {
+ enumTypes[i] = new EnumDescriptor(proto.getEnumType(i), this, null, i);
+ }
+
+ services = new ServiceDescriptor[proto.getServiceCount()];
+ for (int i = 0; i < proto.getServiceCount(); i++) {
+ services[i] = new ServiceDescriptor(proto.getService(i), this, i);
+ }
+
+ extensions = new FieldDescriptor[proto.getExtensionCount()];
+ for (int i = 0; i < proto.getExtensionCount(); i++) {
+ extensions[i] = new FieldDescriptor(
+ proto.getExtension(i), this, null, i, true);
+ }
+ }
+
+ /**
+ * Create a placeholder FileDescriptor for a message Descriptor.
+ */
+ FileDescriptor(String packageName, Descriptor message)
+ throws DescriptorValidationException {
+ this.pool = new DescriptorPool(new FileDescriptor[0], true);
+ this.proto = FileDescriptorProto.newBuilder()
+ .setName(message.getFullName() + ".placeholder.proto")
+ .setPackage(packageName).addMessageType(message.toProto()).build();
+ this.dependencies = new FileDescriptor[0];
+ this.publicDependencies = new FileDescriptor[0];
+
+ messageTypes = new Descriptor[] {message};
+ enumTypes = new EnumDescriptor[0];
+ services = new ServiceDescriptor[0];
+ extensions = new FieldDescriptor[0];
+
+ pool.addPackage(packageName, this);
+ pool.addSymbol(message);
+ }
+
+ /** Look up and cross-link all field types, etc. */
+ private void crossLink() throws DescriptorValidationException {
+ for (final Descriptor messageType : messageTypes) {
+ messageType.crossLink();
+ }
+
+ for (final ServiceDescriptor service : services) {
+ service.crossLink();
+ }
+
+ for (final FieldDescriptor extension : extensions) {
+ extension.crossLink();
+ }
+ }
+
+ /**
+ * Replace our {@link FileDescriptorProto} with the given one, which is
+ * identical except that it might contain extensions that weren't present
+ * in the original. This method is needed for bootstrapping when a file
+ * defines custom options. The options may be defined in the file itself,
+ * so we can't actually parse them until we've constructed the descriptors,
+ * but to construct the descriptors we have to have parsed the descriptor
+ * protos. So, we have to parse the descriptor protos a second time after
+ * constructing the descriptors.
+ */
+ private void setProto(final FileDescriptorProto proto) {
+ this.proto = proto;
+
+ for (int i = 0; i < messageTypes.length; i++) {
+ messageTypes[i].setProto(proto.getMessageType(i));
+ }
+
+ for (int i = 0; i < enumTypes.length; i++) {
+ enumTypes[i].setProto(proto.getEnumType(i));
+ }
+
+ for (int i = 0; i < services.length; i++) {
+ services[i].setProto(proto.getService(i));
+ }
+
+ for (int i = 0; i < extensions.length; i++) {
+ extensions[i].setProto(proto.getExtension(i));
+ }
+ }
+
+ boolean supportsUnknownEnumValue() {
+ return getSyntax() == Syntax.PROTO3;
+ }
+ }
+
+ // =================================================================
+
+ /** Describes a message type. */
+ public static final class Descriptor extends GenericDescriptor {
+ /**
+ * Get the index of this descriptor within its parent. In other words,
+ * given a {@link FileDescriptor} {@code file}, the following is true:
+ * <pre>
+ * for all i in [0, file.getMessageTypeCount()):
+ * file.getMessageType(i).getIndex() == i
+ * </pre>
+ * Similarly, for a {@link Descriptor} {@code messageType}:
+ * <pre>
+ * for all i in [0, messageType.getNestedTypeCount()):
+ * messageType.getNestedType(i).getIndex() == i
+ * </pre>
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public DescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the type's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /**
+ * Get the type's fully-qualified name, within the proto language's
+ * namespace. This differs from the Java name. For example, given this
+ * {@code .proto}:
+ * <pre>
+ * package foo.bar;
+ * option java_package = "com.example.protos"
+ * message Baz {}
+ * </pre>
+ * {@code Baz}'s full name is "foo.bar.Baz".
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the {@link FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** If this is a nested type, get the outer descriptor, otherwise null. */
+ public Descriptor getContainingType() { return containingType; }
+
+ /** Get the {@code MessageOptions}, defined in {@code descriptor.proto}. */
+ public MessageOptions getOptions() { return proto.getOptions(); }
+
+ /** Get a list of this message type's fields. */
+ public List<FieldDescriptor> getFields() {
+ return Collections.unmodifiableList(Arrays.asList(fields));
+ }
+
+ /** Get a list of this message type's oneofs. */
+ public List<OneofDescriptor> getOneofs() {
+ return Collections.unmodifiableList(Arrays.asList(oneofs));
+ }
+
+ /** Get a list of this message type's extensions. */
+ public List<FieldDescriptor> getExtensions() {
+ return Collections.unmodifiableList(Arrays.asList(extensions));
+ }
+
+ /** Get a list of message types nested within this one. */
+ public List<Descriptor> getNestedTypes() {
+ return Collections.unmodifiableList(Arrays.asList(nestedTypes));
+ }
+
+ /** Get a list of enum types nested within this one. */
+ public List<EnumDescriptor> getEnumTypes() {
+ return Collections.unmodifiableList(Arrays.asList(enumTypes));
+ }
+
+ /** Determines if the given field number is an extension. */
+ public boolean isExtensionNumber(final int number) {
+ for (final DescriptorProto.ExtensionRange range :
+ proto.getExtensionRangeList()) {
+ if (range.getStart() <= number && number < range.getEnd()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Determines if the given field number is reserved. */
+ public boolean isReservedNumber(final int number) {
+ for (final DescriptorProto.ReservedRange range :
+ proto.getReservedRangeList()) {
+ if (range.getStart() <= number && number < range.getEnd()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Determines if the given field name is reserved. */
+ public boolean isReservedName(final String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ for (final String reservedName : proto.getReservedNameList()) {
+ if (reservedName.equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Indicates whether the message can be extended. That is, whether it has
+ * any "extensions x to y" ranges declared on it.
+ */
+ public boolean isExtendable() {
+ return proto.getExtensionRangeList().size() != 0;
+ }
+
+ /**
+ * Finds a field by name.
+ * @param name The unqualified name of the field (e.g. "foo").
+ * @return The field's descriptor, or {@code null} if not found.
+ */
+ public FieldDescriptor findFieldByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
+ if (result != null && result instanceof FieldDescriptor) {
+ return (FieldDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Finds a field by field number.
+ * @param number The field number within this message type.
+ * @return The field's descriptor, or {@code null} if not found.
+ */
+ public FieldDescriptor findFieldByNumber(final int number) {
+ return file.pool.fieldsByNumber.get(
+ new DescriptorPool.DescriptorIntPair(this, number));
+ }
+
+ /**
+ * Finds a nested message type by name.
+ * @param name The unqualified name of the nested type (e.g. "Foo").
+ * @return The types's descriptor, or {@code null} if not found.
+ */
+ public Descriptor findNestedTypeByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
+ if (result != null && result instanceof Descriptor) {
+ return (Descriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Finds a nested enum type by name.
+ * @param name The unqualified name of the nested type (e.g. "Foo").
+ * @return The types's descriptor, or {@code null} if not found.
+ */
+ public EnumDescriptor findEnumTypeByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
+ if (result != null && result instanceof EnumDescriptor) {
+ return (EnumDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ private final int index;
+ private DescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+ private final Descriptor containingType;
+ private final Descriptor[] nestedTypes;
+ private final EnumDescriptor[] enumTypes;
+ private final FieldDescriptor[] fields;
+ private final FieldDescriptor[] extensions;
+ private final OneofDescriptor[] oneofs;
+
+ // Used to create a placeholder when the type cannot be found.
+ Descriptor(final String fullname) throws DescriptorValidationException {
+ String name = fullname;
+ String packageName = "";
+ int pos = fullname.lastIndexOf('.');
+ if (pos != -1) {
+ name = fullname.substring(pos + 1);
+ packageName = fullname.substring(0, pos);
+ }
+ this.index = 0;
+ this.proto = DescriptorProto.newBuilder().setName(name).addExtensionRange(
+ DescriptorProto.ExtensionRange.newBuilder().setStart(1)
+ .setEnd(536870912).build()).build();
+ this.fullName = fullname;
+ this.containingType = null;
+
+ this.nestedTypes = new Descriptor[0];
+ this.enumTypes = new EnumDescriptor[0];
+ this.fields = new FieldDescriptor[0];
+ this.extensions = new FieldDescriptor[0];
+ this.oneofs = new OneofDescriptor[0];
+
+ // Create a placeholder FileDescriptor to hold this message.
+ this.file = new FileDescriptor(packageName, this);
+ }
+
+ private Descriptor(final DescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ fullName = computeFullName(file, parent, proto.getName());
+ this.file = file;
+ containingType = parent;
+
+ oneofs = new OneofDescriptor[proto.getOneofDeclCount()];
+ for (int i = 0; i < proto.getOneofDeclCount(); i++) {
+ oneofs[i] = new OneofDescriptor(
+ proto.getOneofDecl(i), file, this, i);
+ }
+
+ nestedTypes = new Descriptor[proto.getNestedTypeCount()];
+ for (int i = 0; i < proto.getNestedTypeCount(); i++) {
+ nestedTypes[i] = new Descriptor(
+ proto.getNestedType(i), file, this, i);
+ }
+
+ enumTypes = new EnumDescriptor[proto.getEnumTypeCount()];
+ for (int i = 0; i < proto.getEnumTypeCount(); i++) {
+ enumTypes[i] = new EnumDescriptor(
+ proto.getEnumType(i), file, this, i);
+ }
+
+ fields = new FieldDescriptor[proto.getFieldCount()];
+ for (int i = 0; i < proto.getFieldCount(); i++) {
+ fields[i] = new FieldDescriptor(
+ proto.getField(i), file, this, i, false);
+ }
+
+ extensions = new FieldDescriptor[proto.getExtensionCount()];
+ for (int i = 0; i < proto.getExtensionCount(); i++) {
+ extensions[i] = new FieldDescriptor(
+ proto.getExtension(i), file, this, i, true);
+ }
+
+ for (int i = 0; i < proto.getOneofDeclCount(); i++) {
+ oneofs[i].fields = new FieldDescriptor[oneofs[i].getFieldCount()];
+ oneofs[i].fieldCount = 0;
+ }
+ for (int i = 0; i < proto.getFieldCount(); i++) {
+ OneofDescriptor oneofDescriptor = fields[i].getContainingOneof();
+ if (oneofDescriptor != null) {
+ oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i];
+ }
+ }
+
+ file.pool.addSymbol(this);
+ }
+
+ /** Look up and cross-link all field types, etc. */
+ private void crossLink() throws DescriptorValidationException {
+ for (final Descriptor nestedType : nestedTypes) {
+ nestedType.crossLink();
+ }
+
+ for (final FieldDescriptor field : fields) {
+ field.crossLink();
+ }
+
+ for (final FieldDescriptor extension : extensions) {
+ extension.crossLink();
+ }
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final DescriptorProto proto) {
+ this.proto = proto;
+
+ for (int i = 0; i < nestedTypes.length; i++) {
+ nestedTypes[i].setProto(proto.getNestedType(i));
+ }
+
+ for (int i = 0; i < oneofs.length; i++) {
+ oneofs[i].setProto(proto.getOneofDecl(i));
+ }
+
+ for (int i = 0; i < enumTypes.length; i++) {
+ enumTypes[i].setProto(proto.getEnumType(i));
+ }
+
+ for (int i = 0; i < fields.length; i++) {
+ fields[i].setProto(proto.getField(i));
+ }
+
+ for (int i = 0; i < extensions.length; i++) {
+ extensions[i].setProto(proto.getExtension(i));
+ }
+ }
+ }
+
+ // =================================================================
+
+ /** Describes a field of a message type. */
+ public static final class FieldDescriptor
+ extends GenericDescriptor
+ implements Comparable<FieldDescriptor>,
+ FieldSet.FieldDescriptorLite<FieldDescriptor> {
+ /**
+ * Get the index of this descriptor within its parent.
+ * @see Descriptors.Descriptor#getIndex()
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public FieldDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the field's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /** Get the field's number. */
+ @Override
+ public int getNumber() {
+ return proto.getNumber();
+ }
+
+ /**
+ * Get the field's fully-qualified name.
+ * @see Descriptors.Descriptor#getFullName()
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the JSON name of this field. */
+ public String getJsonName() {
+ return jsonName;
+ }
+
+ /**
+ * Get the field's java type. This is just for convenience. Every
+ * {@code FieldDescriptorProto.Type} maps to exactly one Java type.
+ */
+ public JavaType getJavaType() { return type.getJavaType(); }
+
+ /** For internal use only. */
+ @Override
+ public WireFormat.JavaType getLiteJavaType() {
+ return getLiteType().getJavaType();
+ }
+
+ /** Get the {@code FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** Get the field's declared type. */
+ public Type getType() { return type; }
+
+ /** For internal use only. */
+ @Override
+ public WireFormat.FieldType getLiteType() {
+ return table[type.ordinal()];
+ }
+
+ /** For internal use only. */
+ public boolean needsUtf8Check() {
+ if (type != Type.STRING) {
+ return false;
+ }
+ if (getContainingType().getOptions().getMapEntry()) {
+ // Always enforce strict UTF-8 checking for map fields.
+ return true;
+ }
+ if (getFile().getSyntax() == Syntax.PROTO3) {
+ return true;
+ }
+ return getFile().getOptions().getJavaStringCheckUtf8();
+ }
+
+ public boolean isMapField() {
+ return getType() == Type.MESSAGE && isRepeated()
+ && getMessageType().getOptions().getMapEntry();
+ }
+
+ // I'm pretty sure values() constructs a new array every time, since there
+ // is nothing stopping the caller from mutating the array. Therefore we
+ // make a static copy here.
+ private static final WireFormat.FieldType[] table =
+ WireFormat.FieldType.values();
+
+ /** Is this field declared required? */
+ public boolean isRequired() {
+ return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REQUIRED;
+ }
+
+ /** Is this field declared optional? */
+ public boolean isOptional() {
+ return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL;
+ }
+
+ /** Is this field declared repeated? */
+ @Override
+ public boolean isRepeated() {
+ return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
+ }
+
+ /** Does this field have the {@code [packed = true]} option or is this field
+ * packable in proto3 and not explicitly setted to unpacked?
+ */
+ @Override
+ public boolean isPacked() {
+ if (!isPackable()) {
+ return false;
+ }
+ if (getFile().getSyntax() == FileDescriptor.Syntax.PROTO2) {
+ return getOptions().getPacked();
+ } else {
+ return !getOptions().hasPacked() || getOptions().getPacked();
+ }
+ }
+
+ /** Can this field be packed? i.e. is it a repeated primitive field? */
+ public boolean isPackable() {
+ return isRepeated() && getLiteType().isPackable();
+ }
+
+ /** Returns true if the field had an explicitly-defined default value. */
+ public boolean hasDefaultValue() { return proto.hasDefaultValue(); }
+
+ /**
+ * Returns the field's default value. Valid for all types except for
+ * messages and groups. For all other types, the object returned is of
+ * the same class that would returned by Message.getField(this).
+ */
+ public Object getDefaultValue() {
+ if (getJavaType() == JavaType.MESSAGE) {
+ throw new UnsupportedOperationException(
+ "FieldDescriptor.getDefaultValue() called on an embedded message " +
+ "field.");
+ }
+ return defaultValue;
+ }
+
+ /** Get the {@code FieldOptions}, defined in {@code descriptor.proto}. */
+ public FieldOptions getOptions() { return proto.getOptions(); }
+
+ /** Is this field an extension? */
+ public boolean isExtension() { return proto.hasExtendee(); }
+
+ /**
+ * Get the field's containing type. For extensions, this is the type being
+ * extended, not the location where the extension was defined. See
+ * {@link #getExtensionScope()}.
+ */
+ public Descriptor getContainingType() { return containingType; }
+
+ /** Get the field's containing oneof. */
+ public OneofDescriptor getContainingOneof() { return containingOneof; }
+
+ /**
+ * For extensions defined nested within message types, gets the outer
+ * type. Not valid for non-extension fields. For example, consider
+ * this {@code .proto} file:
+ * <pre>
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ * extend Foo {
+ * optional int32 baz = 1234;
+ * }
+ * message Bar {
+ * extend Foo {
+ * optional int32 qux = 4321;
+ * }
+ * }
+ * </pre>
+ * Both {@code baz}'s and {@code qux}'s containing type is {@code Foo}.
+ * However, {@code baz}'s extension scope is {@code null} while
+ * {@code qux}'s extension scope is {@code Bar}.
+ */
+ public Descriptor getExtensionScope() {
+ if (!isExtension()) {
+ throw new UnsupportedOperationException(
+ "This field is not an extension.");
+ }
+ return extensionScope;
+ }
+
+ /** For embedded message and group fields, gets the field's type. */
+ public Descriptor getMessageType() {
+ if (getJavaType() != JavaType.MESSAGE) {
+ throw new UnsupportedOperationException(
+ "This field is not of message type.");
+ }
+ return messageType;
+ }
+
+ /** For enum fields, gets the field's type. */
+ @Override
+ public EnumDescriptor getEnumType() {
+ if (getJavaType() != JavaType.ENUM) {
+ throw new UnsupportedOperationException(
+ "This field is not of enum type.");
+ }
+ return enumType;
+ }
+
+ /**
+ * Compare with another {@code FieldDescriptor}. This orders fields in
+ * "canonical" order, which simply means ascending order by field number.
+ * {@code other} must be a field of the same type -- i.e.
+ * {@code getContainingType()} must return the same {@code Descriptor} for
+ * both fields.
+ *
+ * @return negative, zero, or positive if {@code this} is less than,
+ * equal to, or greater than {@code other}, respectively.
+ */
+ @Override
+ public int compareTo(final FieldDescriptor other) {
+ if (other.containingType != containingType) {
+ throw new IllegalArgumentException(
+ "FieldDescriptors can only be compared to other FieldDescriptors " +
+ "for fields of the same message type.");
+ }
+ return getNumber() - other.getNumber();
+ }
+
+ @Override
+ public String toString() {
+ return getFullName();
+ }
+
+ private final int index;
+
+ private FieldDescriptorProto proto;
+ private final String fullName;
+ private final String jsonName;
+ private final FileDescriptor file;
+ private final Descriptor extensionScope;
+
+ // Possibly initialized during cross-linking.
+ private Type type;
+ private Descriptor containingType;
+ private Descriptor messageType;
+ private OneofDescriptor containingOneof;
+ private EnumDescriptor enumType;
+ private Object defaultValue;
+
+ public enum Type {
+ DOUBLE (JavaType.DOUBLE ),
+ FLOAT (JavaType.FLOAT ),
+ INT64 (JavaType.LONG ),
+ UINT64 (JavaType.LONG ),
+ INT32 (JavaType.INT ),
+ FIXED64 (JavaType.LONG ),
+ FIXED32 (JavaType.INT ),
+ BOOL (JavaType.BOOLEAN ),
+ STRING (JavaType.STRING ),
+ GROUP (JavaType.MESSAGE ),
+ MESSAGE (JavaType.MESSAGE ),
+ BYTES (JavaType.BYTE_STRING),
+ UINT32 (JavaType.INT ),
+ ENUM (JavaType.ENUM ),
+ SFIXED32(JavaType.INT ),
+ SFIXED64(JavaType.LONG ),
+ SINT32 (JavaType.INT ),
+ SINT64 (JavaType.LONG );
+
+ Type(final JavaType javaType) {
+ this.javaType = javaType;
+ }
+
+ private JavaType javaType;
+
+ public FieldDescriptorProto.Type toProto() {
+ return FieldDescriptorProto.Type.forNumber(ordinal() + 1);
+ }
+ public JavaType getJavaType() { return javaType; }
+
+ public static Type valueOf(final FieldDescriptorProto.Type type) {
+ return values()[type.getNumber() - 1];
+ }
+ }
+
+ static {
+ // Refuse to init if someone added a new declared type.
+ if (Type.values().length != FieldDescriptorProto.Type.values().length) {
+ throw new RuntimeException(""
+ + "descriptor.proto has a new declared type but Descriptors.java "
+ + "wasn't updated.");
+ }
+ }
+
+ public enum JavaType {
+ INT(0),
+ LONG(0L),
+ FLOAT(0F),
+ DOUBLE(0D),
+ BOOLEAN(false),
+ STRING(""),
+ BYTE_STRING(ByteString.EMPTY),
+ ENUM(null),
+ MESSAGE(null);
+
+ JavaType(final Object defaultDefault) {
+ this.defaultDefault = defaultDefault;
+ }
+
+ /**
+ * The default default value for fields of this type, if it's a primitive
+ * type. This is meant for use inside this file only, hence is private.
+ */
+ private final Object defaultDefault;
+ }
+
+ // This method should match exactly with the ToJsonName() function in C++
+ // descriptor.cc.
+ private static String fieldNameToJsonName(String name) {
+ StringBuilder result = new StringBuilder(name.length());
+ boolean isNextUpperCase = false;
+ for (int i = 0; i < name.length(); i++) {
+ Character ch = name.charAt(i);
+ if (ch == '_') {
+ isNextUpperCase = true;
+ } else if (isNextUpperCase) {
+ result.append(Character.toUpperCase(ch));
+ isNextUpperCase = false;
+ } else {
+ result.append(ch);
+ }
+ }
+ return result.toString();
+ }
+
+ private FieldDescriptor(final FieldDescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index,
+ final boolean isExtension)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ fullName = computeFullName(file, parent, proto.getName());
+ this.file = file;
+ if (proto.hasJsonName()) {
+ jsonName = proto.getJsonName();
+ } else {
+ jsonName = fieldNameToJsonName(proto.getName());
+ }
+
+ if (proto.hasType()) {
+ type = Type.valueOf(proto.getType());
+ }
+
+ if (getNumber() <= 0) {
+ throw new DescriptorValidationException(this,
+ "Field numbers must be positive integers.");
+ }
+
+ if (isExtension) {
+ if (!proto.hasExtendee()) {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.extendee not set for extension field.");
+ }
+ containingType = null; // Will be filled in when cross-linking
+ if (parent != null) {
+ extensionScope = parent;
+ } else {
+ extensionScope = null;
+ }
+
+ if (proto.hasOneofIndex()) {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.oneof_index set for extension field.");
+ }
+ containingOneof = null;
+ } else {
+ if (proto.hasExtendee()) {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.extendee set for non-extension field.");
+ }
+ containingType = parent;
+
+ if (proto.hasOneofIndex()) {
+ if (proto.getOneofIndex() < 0 ||
+ proto.getOneofIndex() >= parent.toProto().getOneofDeclCount()) {
+ throw new DescriptorValidationException(this,
+ "FieldDescriptorProto.oneof_index is out of range for type "
+ + parent.getName());
+ }
+ containingOneof = parent.getOneofs().get(proto.getOneofIndex());
+ containingOneof.fieldCount++;
+ } else {
+ containingOneof = null;
+ }
+ extensionScope = null;
+ }
+
+ file.pool.addSymbol(this);
+ }
+
+ /** Look up and cross-link all field types, etc. */
+ private void crossLink() throws DescriptorValidationException {
+ if (proto.hasExtendee()) {
+ final GenericDescriptor extendee =
+ file.pool.lookupSymbol(proto.getExtendee(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
+ if (!(extendee instanceof Descriptor)) {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getExtendee() + "\" is not a message type.");
+ }
+ containingType = (Descriptor)extendee;
+
+ if (!getContainingType().isExtensionNumber(getNumber())) {
+ throw new DescriptorValidationException(this,
+ '\"' + getContainingType().getFullName() +
+ "\" does not declare " + getNumber() +
+ " as an extension number.");
+ }
+ }
+
+ if (proto.hasTypeName()) {
+ final GenericDescriptor typeDescriptor =
+ file.pool.lookupSymbol(proto.getTypeName(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
+
+ if (!proto.hasType()) {
+ // Choose field type based on symbol.
+ if (typeDescriptor instanceof Descriptor) {
+ type = Type.MESSAGE;
+ } else if (typeDescriptor instanceof EnumDescriptor) {
+ type = Type.ENUM;
+ } else {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getTypeName() + "\" is not a type.");
+ }
+ }
+
+ if (getJavaType() == JavaType.MESSAGE) {
+ if (!(typeDescriptor instanceof Descriptor)) {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getTypeName() + "\" is not a message type.");
+ }
+ messageType = (Descriptor)typeDescriptor;
+
+ if (proto.hasDefaultValue()) {
+ throw new DescriptorValidationException(this,
+ "Messages can't have default values.");
+ }
+ } else if (getJavaType() == JavaType.ENUM) {
+ if (!(typeDescriptor instanceof EnumDescriptor)) {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getTypeName() + "\" is not an enum type.");
+ }
+ enumType = (EnumDescriptor)typeDescriptor;
+ } else {
+ throw new DescriptorValidationException(this,
+ "Field with primitive type has type_name.");
+ }
+ } else {
+ if (getJavaType() == JavaType.MESSAGE ||
+ getJavaType() == JavaType.ENUM) {
+ throw new DescriptorValidationException(this,
+ "Field with message or enum type missing type_name.");
+ }
+ }
+
+ // Only repeated primitive fields may be packed.
+ if (proto.getOptions().getPacked() && !isPackable()) {
+ throw new DescriptorValidationException(this,
+ "[packed = true] can only be specified for repeated primitive " +
+ "fields.");
+ }
+
+ // We don't attempt to parse the default value until here because for
+ // enums we need the enum type's descriptor.
+ if (proto.hasDefaultValue()) {
+ if (isRepeated()) {
+ throw new DescriptorValidationException(this,
+ "Repeated fields cannot have default values.");
+ }
+
+ try {
+ switch (getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ defaultValue = TextFormat.parseInt32(proto.getDefaultValue());
+ break;
+ case UINT32:
+ case FIXED32:
+ defaultValue = TextFormat.parseUInt32(proto.getDefaultValue());
+ break;
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ defaultValue = TextFormat.parseInt64(proto.getDefaultValue());
+ break;
+ case UINT64:
+ case FIXED64:
+ defaultValue = TextFormat.parseUInt64(proto.getDefaultValue());
+ break;
+ case FLOAT:
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Float.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Float.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Float.NaN;
+ } else {
+ defaultValue = Float.valueOf(proto.getDefaultValue());
+ }
+ break;
+ case DOUBLE:
+ if (proto.getDefaultValue().equals("inf")) {
+ defaultValue = Double.POSITIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("-inf")) {
+ defaultValue = Double.NEGATIVE_INFINITY;
+ } else if (proto.getDefaultValue().equals("nan")) {
+ defaultValue = Double.NaN;
+ } else {
+ defaultValue = Double.valueOf(proto.getDefaultValue());
+ }
+ break;
+ case BOOL:
+ defaultValue = Boolean.valueOf(proto.getDefaultValue());
+ break;
+ case STRING:
+ defaultValue = proto.getDefaultValue();
+ break;
+ case BYTES:
+ try {
+ defaultValue =
+ TextFormat.unescapeBytes(proto.getDefaultValue());
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ throw new DescriptorValidationException(this,
+ "Couldn't parse default value: " + e.getMessage(), e);
+ }
+ break;
+ case ENUM:
+ defaultValue = enumType.findValueByName(proto.getDefaultValue());
+ if (defaultValue == null) {
+ throw new DescriptorValidationException(this,
+ "Unknown enum default value: \"" +
+ proto.getDefaultValue() + '\"');
+ }
+ break;
+ case MESSAGE:
+ case GROUP:
+ throw new DescriptorValidationException(this,
+ "Message type had default value.");
+ }
+ } catch (NumberFormatException e) {
+ throw new DescriptorValidationException(this,
+ "Could not parse default value: \"" +
+ proto.getDefaultValue() + '\"', e);
+ }
+ } else {
+ // Determine the default default for this field.
+ if (isRepeated()) {
+ defaultValue = Collections.emptyList();
+ } else {
+ switch (getJavaType()) {
+ case ENUM:
+ // We guarantee elsewhere that an enum type always has at least
+ // one possible value.
+ defaultValue = enumType.getValues().get(0);
+ break;
+ case MESSAGE:
+ defaultValue = null;
+ break;
+ default:
+ defaultValue = getJavaType().defaultDefault;
+ break;
+ }
+ }
+ }
+
+ if (!isExtension()) {
+ file.pool.addFieldByNumber(this);
+ }
+
+ if (containingType != null &&
+ containingType.getOptions().getMessageSetWireFormat()) {
+ if (isExtension()) {
+ if (!isOptional() || getType() != Type.MESSAGE) {
+ throw new DescriptorValidationException(this,
+ "Extensions of MessageSets must be optional messages.");
+ }
+ } else {
+ throw new DescriptorValidationException(this,
+ "MessageSets cannot have fields, only extensions.");
+ }
+ }
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final FieldDescriptorProto proto) {
+ this.proto = proto;
+ }
+
+ /**
+ * For internal use only. This is to satisfy the FieldDescriptorLite
+ * interface.
+ */
+ @Override
+ public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
+ // FieldDescriptors are only used with non-lite messages so we can just
+ // down-cast and call mergeFrom directly.
+ return ((Message.Builder) to).mergeFrom((Message) from);
+ }
+
+ }
+
+ // =================================================================
+
+ /** Describes an enum type. */
+ public static final class EnumDescriptor extends GenericDescriptor
+ implements Internal.EnumLiteMap<EnumValueDescriptor> {
+ /**
+ * Get the index of this descriptor within its parent.
+ * @see Descriptors.Descriptor#getIndex()
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public EnumDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the type's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /**
+ * Get the type's fully-qualified name.
+ * @see Descriptors.Descriptor#getFullName()
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the {@link FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** If this is a nested type, get the outer descriptor, otherwise null. */
+ public Descriptor getContainingType() { return containingType; }
+
+ /** Get the {@code EnumOptions}, defined in {@code descriptor.proto}. */
+ public EnumOptions getOptions() { return proto.getOptions(); }
+
+ /** Get a list of defined values for this enum. */
+ public List<EnumValueDescriptor> getValues() {
+ return Collections.unmodifiableList(Arrays.asList(values));
+ }
+
+ /**
+ * Find an enum value by name.
+ * @param name The unqualified name of the value (e.g. "FOO").
+ * @return the value's descriptor, or {@code null} if not found.
+ */
+ public EnumValueDescriptor findValueByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
+ if (result != null && result instanceof EnumValueDescriptor) {
+ return (EnumValueDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Find an enum value by number. If multiple enum values have the same
+ * number, this returns the first defined value with that number.
+ * @param number The value's number.
+ * @return the value's descriptor, or {@code null} if not found.
+ */
+ @Override
+ public EnumValueDescriptor findValueByNumber(final int number) {
+ return file.pool.enumValuesByNumber.get(
+ new DescriptorPool.DescriptorIntPair(this, number));
+ }
+
+ /**
+ * Get the enum value for a number. If no enum value has this number,
+ * construct an EnumValueDescriptor for it.
+ */
+ public EnumValueDescriptor findValueByNumberCreatingIfUnknown(final int number) {
+ EnumValueDescriptor result = findValueByNumber(number);
+ if (result != null) {
+ return result;
+ }
+ // The number represents an unknown enum value.
+ synchronized (this) {
+ // Descriptors are compared by object identity so for the same number
+ // we need to return the same EnumValueDescriptor object. This means
+ // we have to store created EnumValueDescriptors. However, as there
+ // are potentially 2G unknown enum values, storing all of these
+ // objects persistently will consume lots of memory for long-running
+ // services and it's also unnecessary as not many EnumValueDescriptors
+ // will be used at the same time.
+ //
+ // To solve the problem we take advantage of Java's weak references and
+ // rely on gc to release unused descriptors.
+ //
+ // Here is how it works:
+ // * We store unknown EnumValueDescriptors in a WeakHashMap with the
+ // value being a weak reference to the descriptor.
+ // * The descriptor holds a strong reference to the key so as long
+ // as the EnumValueDescriptor is in use, the key will be there
+ // and the corresponding map entry will be there. Following-up
+ // queries with the same number will return the same descriptor.
+ // * If the user no longer uses an unknown EnumValueDescriptor,
+ // it will be gc-ed since we only hold a weak reference to it in
+ // the map. The key in the corresponding map entry will also be
+ // gc-ed as the only strong reference to it is in the descriptor
+ // which is just gc-ed. With the key being gone WeakHashMap will
+ // then remove the whole entry. This way unknown descriptors will
+ // be freed automatically and we don't need to do anything to
+ // clean-up unused map entries.
+
+ // Note: We must use "new Integer(number)" here because we don't want
+ // these Integer objects to be cached.
+ Integer key = new Integer(number);
+ WeakReference<EnumValueDescriptor> reference = unknownValues.get(key);
+ if (reference != null) {
+ result = reference.get();
+ }
+ if (result == null) {
+ result = new EnumValueDescriptor(file, this, key);
+ unknownValues.put(key, new WeakReference<EnumValueDescriptor>(result));
+ }
+ }
+ return result;
+ }
+
+ // Used in tests only.
+ int getUnknownEnumValueDescriptorCount() {
+ return unknownValues.size();
+ }
+
+ private final int index;
+ private EnumDescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+ private final Descriptor containingType;
+ private EnumValueDescriptor[] values;
+ private final WeakHashMap<Integer, WeakReference<EnumValueDescriptor>> unknownValues =
+ new WeakHashMap<Integer, WeakReference<EnumValueDescriptor>>();
+
+ private EnumDescriptor(final EnumDescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ fullName = computeFullName(file, parent, proto.getName());
+ this.file = file;
+ containingType = parent;
+
+ if (proto.getValueCount() == 0) {
+ // We cannot allow enums with no values because this would mean there
+ // would be no valid default value for fields of this type.
+ throw new DescriptorValidationException(this,
+ "Enums must contain at least one value.");
+ }
+
+ values = new EnumValueDescriptor[proto.getValueCount()];
+ for (int i = 0; i < proto.getValueCount(); i++) {
+ values[i] = new EnumValueDescriptor(
+ proto.getValue(i), file, this, i);
+ }
+
+ file.pool.addSymbol(this);
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final EnumDescriptorProto proto) {
+ this.proto = proto;
+
+ for (int i = 0; i < values.length; i++) {
+ values[i].setProto(proto.getValue(i));
+ }
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Describes one value within an enum type. Note that multiple defined
+ * values may have the same number. In generated Java code, all values
+ * with the same number after the first become aliases of the first.
+ * However, they still have independent EnumValueDescriptors.
+ */
+ public static final class EnumValueDescriptor extends GenericDescriptor
+ implements Internal.EnumLite {
+ /**
+ * Get the index of this descriptor within its parent.
+ * @see Descriptors.Descriptor#getIndex()
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public EnumValueDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the value's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /** Get the value's number. */
+ @Override
+ public int getNumber() {
+ return proto.getNumber();
+ }
+
+ @Override
+ public String toString() { return proto.getName(); }
+
+ /**
+ * Get the value's fully-qualified name.
+ * @see Descriptors.Descriptor#getFullName()
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the {@link FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** Get the value's enum type. */
+ public EnumDescriptor getType() { return type; }
+
+ /**
+ * Get the {@code EnumValueOptions}, defined in {@code descriptor.proto}.
+ */
+ public EnumValueOptions getOptions() { return proto.getOptions(); }
+
+ private final int index;
+ private EnumValueDescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+ private final EnumDescriptor type;
+
+ private EnumValueDescriptor(final EnumValueDescriptorProto proto,
+ final FileDescriptor file,
+ final EnumDescriptor parent,
+ final int index)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ this.file = file;
+ type = parent;
+
+ fullName = parent.getFullName() + '.' + proto.getName();
+
+ file.pool.addSymbol(this);
+ file.pool.addEnumValueByNumber(this);
+ }
+
+ private Integer number;
+ // Create an unknown enum value.
+ private EnumValueDescriptor(
+ final FileDescriptor file,
+ final EnumDescriptor parent,
+ final Integer number) {
+ String name = "UNKNOWN_ENUM_VALUE_" + parent.getName() + "_" + number;
+ EnumValueDescriptorProto proto = EnumValueDescriptorProto
+ .newBuilder().setName(name).setNumber(number).build();
+ this.index = -1;
+ this.proto = proto;
+ this.file = file;
+ this.type = parent;
+ this.fullName = parent.getFullName() + '.' + proto.getName();
+ this.number = number;
+
+ // Don't add this descriptor into pool.
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final EnumValueDescriptorProto proto) {
+ this.proto = proto;
+ }
+ }
+
+ // =================================================================
+
+ /** Describes a service type. */
+ public static final class ServiceDescriptor extends GenericDescriptor {
+ /**
+ * Get the index of this descriptor within its parent.
+ * * @see Descriptors.Descriptor#getIndex()
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public ServiceDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the type's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /**
+ * Get the type's fully-qualified name.
+ * @see Descriptors.Descriptor#getFullName()
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the {@link FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */
+ public ServiceOptions getOptions() { return proto.getOptions(); }
+
+ /** Get a list of methods for this service. */
+ public List<MethodDescriptor> getMethods() {
+ return Collections.unmodifiableList(Arrays.asList(methods));
+ }
+
+ /**
+ * Find a method by name.
+ * @param name The unqualified name of the method (e.g. "Foo").
+ * @return the method's descriptor, or {@code null} if not found.
+ */
+ public MethodDescriptor findMethodByName(final String name) {
+ final GenericDescriptor result =
+ file.pool.findSymbol(fullName + '.' + name);
+ if (result != null && result instanceof MethodDescriptor) {
+ return (MethodDescriptor)result;
+ } else {
+ return null;
+ }
+ }
+
+ private final int index;
+ private ServiceDescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+ private MethodDescriptor[] methods;
+
+ private ServiceDescriptor(final ServiceDescriptorProto proto,
+ final FileDescriptor file,
+ final int index)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ fullName = computeFullName(file, null, proto.getName());
+ this.file = file;
+
+ methods = new MethodDescriptor[proto.getMethodCount()];
+ for (int i = 0; i < proto.getMethodCount(); i++) {
+ methods[i] = new MethodDescriptor(
+ proto.getMethod(i), file, this, i);
+ }
+
+ file.pool.addSymbol(this);
+ }
+
+ private void crossLink() throws DescriptorValidationException {
+ for (final MethodDescriptor method : methods) {
+ method.crossLink();
+ }
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final ServiceDescriptorProto proto) {
+ this.proto = proto;
+
+ for (int i = 0; i < methods.length; i++) {
+ methods[i].setProto(proto.getMethod(i));
+ }
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Describes one method within a service type.
+ */
+ public static final class MethodDescriptor extends GenericDescriptor {
+ /**
+ * Get the index of this descriptor within its parent.
+ * * @see Descriptors.Descriptor#getIndex()
+ */
+ public int getIndex() { return index; }
+
+ /** Convert the descriptor to its protocol message representation. */
+ @Override
+ public MethodDescriptorProto toProto() {
+ return proto;
+ }
+
+ /** Get the method's unqualified name. */
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
+
+ /**
+ * Get the method's fully-qualified name.
+ * @see Descriptors.Descriptor#getFullName()
+ */
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+
+ /** Get the {@link FileDescriptor} containing this descriptor. */
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ /** Get the method's service type. */
+ public ServiceDescriptor getService() { return service; }
+
+ /** Get the method's input type. */
+ public Descriptor getInputType() { return inputType; }
+
+ /** Get the method's output type. */
+ public Descriptor getOutputType() { return outputType; }
+
+ /**
+ * Get the {@code MethodOptions}, defined in {@code descriptor.proto}.
+ */
+ public MethodOptions getOptions() { return proto.getOptions(); }
+
+ private final int index;
+ private MethodDescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+ private final ServiceDescriptor service;
+
+ // Initialized during cross-linking.
+ private Descriptor inputType;
+ private Descriptor outputType;
+
+ private MethodDescriptor(final MethodDescriptorProto proto,
+ final FileDescriptor file,
+ final ServiceDescriptor parent,
+ final int index)
+ throws DescriptorValidationException {
+ this.index = index;
+ this.proto = proto;
+ this.file = file;
+ service = parent;
+
+ fullName = parent.getFullName() + '.' + proto.getName();
+
+ file.pool.addSymbol(this);
+ }
+
+ private void crossLink() throws DescriptorValidationException {
+ final GenericDescriptor input =
+ file.pool.lookupSymbol(proto.getInputType(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
+ if (!(input instanceof Descriptor)) {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getInputType() + "\" is not a message type.");
+ }
+ inputType = (Descriptor)input;
+
+ final GenericDescriptor output =
+ file.pool.lookupSymbol(proto.getOutputType(), this,
+ DescriptorPool.SearchFilter.TYPES_ONLY);
+ if (!(output instanceof Descriptor)) {
+ throw new DescriptorValidationException(this,
+ '\"' + proto.getOutputType() + "\" is not a message type.");
+ }
+ outputType = (Descriptor)output;
+ }
+
+ /** See {@link FileDescriptor#setProto}. */
+ private void setProto(final MethodDescriptorProto proto) {
+ this.proto = proto;
+ }
+ }
+
+ // =================================================================
+
+ private static String computeFullName(final FileDescriptor file,
+ final Descriptor parent,
+ final String name) {
+ if (parent != null) {
+ return parent.getFullName() + '.' + name;
+ } else if (file.getPackage().length() > 0) {
+ return file.getPackage() + '.' + name;
+ } else {
+ return name;
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * All descriptors implement this to make it easier to implement tools like
+ * {@code DescriptorPool}.<p>
+ *
+ * This class is public so that the methods it exposes can be called from
+ * outside of this package. However, it should only be subclassed from
+ * nested classes of Descriptors.
+ */
+ public abstract static class GenericDescriptor {
+ public abstract Message toProto();
+ public abstract String getName();
+ public abstract String getFullName();
+ public abstract FileDescriptor getFile();
+ }
+
+ /**
+ * Thrown when building descriptors fails because the source DescriptorProtos
+ * are not valid.
+ */
+ public static class DescriptorValidationException extends Exception {
+ private static final long serialVersionUID = 5750205775490483148L;
+
+ /** Gets the full name of the descriptor where the error occurred. */
+ public String getProblemSymbolName() { return name; }
+
+ /**
+ * Gets the protocol message representation of the invalid descriptor.
+ */
+ public Message getProblemProto() { return proto; }
+
+ /**
+ * Gets a human-readable description of the error.
+ */
+ public String getDescription() { return description; }
+
+ private final String name;
+ private final Message proto;
+ private final String description;
+
+ private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description) {
+ super(problemDescriptor.getFullName() + ": " + description);
+
+ // Note that problemDescriptor may be partially uninitialized, so we
+ // don't want to expose it directly to the user. So, we only provide
+ // the name and the original proto.
+ name = problemDescriptor.getFullName();
+ proto = problemDescriptor.toProto();
+ this.description = description;
+ }
+
+ private DescriptorValidationException(
+ final GenericDescriptor problemDescriptor,
+ final String description,
+ final Throwable cause) {
+ this(problemDescriptor, description);
+ initCause(cause);
+ }
+
+ private DescriptorValidationException(
+ final FileDescriptor problemDescriptor,
+ final String description) {
+ super(problemDescriptor.getName() + ": " + description);
+
+ // Note that problemDescriptor may be partially uninitialized, so we
+ // don't want to expose it directly to the user. So, we only provide
+ // the name and the original proto.
+ name = problemDescriptor.getName();
+ proto = problemDescriptor.toProto();
+ this.description = description;
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * A private helper class which contains lookup tables containing all the
+ * descriptors defined in a particular file.
+ */
+ private static final class DescriptorPool {
+
+ /** Defines what subclass of descriptors to search in the descriptor pool.
+ */
+ enum SearchFilter {
+ TYPES_ONLY, AGGREGATES_ONLY, ALL_SYMBOLS
+ }
+
+ DescriptorPool(final FileDescriptor[] dependencies,
+ boolean allowUnknownDependencies) {
+ this.dependencies = new HashSet<FileDescriptor>();
+ this.allowUnknownDependencies = allowUnknownDependencies;
+
+ for (int i = 0; i < dependencies.length; i++) {
+ this.dependencies.add(dependencies[i]);
+ importPublicDependencies(dependencies[i]);
+ }
+
+ for (final FileDescriptor dependency : this.dependencies) {
+ try {
+ addPackage(dependency.getPackage(), dependency);
+ } catch (DescriptorValidationException e) {
+ // Can't happen, because addPackage() only fails when the name
+ // conflicts with a non-package, but we have not yet added any
+ // non-packages at this point.
+ throw new AssertionError(e);
+ }
+ }
+ }
+
+ /** Find and put public dependencies of the file into dependencies set.*/
+ private void importPublicDependencies(final FileDescriptor file) {
+ for (FileDescriptor dependency : file.getPublicDependencies()) {
+ if (dependencies.add(dependency)) {
+ importPublicDependencies(dependency);
+ }
+ }
+ }
+
+ private final Set<FileDescriptor> dependencies;
+ private boolean allowUnknownDependencies;
+
+ private final Map<String, GenericDescriptor> descriptorsByName =
+ new HashMap<String, GenericDescriptor>();
+ private final Map<DescriptorIntPair, FieldDescriptor> fieldsByNumber =
+ new HashMap<DescriptorIntPair, FieldDescriptor>();
+ private final Map<DescriptorIntPair, EnumValueDescriptor> enumValuesByNumber
+ = new HashMap<DescriptorIntPair, EnumValueDescriptor>();
+
+ /** Find a generic descriptor by fully-qualified name. */
+ GenericDescriptor findSymbol(final String fullName) {
+ return findSymbol(fullName, SearchFilter.ALL_SYMBOLS);
+ }
+
+ /** Find a descriptor by fully-qualified name and given option to only
+ * search valid field type descriptors.
+ */
+ GenericDescriptor findSymbol(final String fullName,
+ final SearchFilter filter) {
+ GenericDescriptor result = descriptorsByName.get(fullName);
+ if (result != null) {
+ if ((filter==SearchFilter.ALL_SYMBOLS) ||
+ ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+ ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+ return result;
+ }
+ }
+
+ for (final FileDescriptor dependency : dependencies) {
+ result = dependency.pool.descriptorsByName.get(fullName);
+ if (result != null) {
+ if ((filter==SearchFilter.ALL_SYMBOLS) ||
+ ((filter==SearchFilter.TYPES_ONLY) && isType(result)) ||
+ ((filter==SearchFilter.AGGREGATES_ONLY) && isAggregate(result))) {
+ return result;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /** Checks if the descriptor is a valid type for a message field. */
+ boolean isType(GenericDescriptor descriptor) {
+ return (descriptor instanceof Descriptor) ||
+ (descriptor instanceof EnumDescriptor);
+ }
+
+ /** Checks if the descriptor is a valid namespace type. */
+ boolean isAggregate(GenericDescriptor descriptor) {
+ return (descriptor instanceof Descriptor) ||
+ (descriptor instanceof EnumDescriptor) ||
+ (descriptor instanceof PackageDescriptor) ||
+ (descriptor instanceof ServiceDescriptor);
+ }
+
+ /**
+ * Look up a type descriptor by name, relative to some other descriptor.
+ * The name may be fully-qualified (with a leading '.'),
+ * partially-qualified, or unqualified. C++-like name lookup semantics
+ * are used to search for the matching descriptor.
+ */
+ GenericDescriptor lookupSymbol(final String name,
+ final GenericDescriptor relativeTo,
+ final DescriptorPool.SearchFilter filter)
+ throws DescriptorValidationException {
+ // TODO(kenton): This could be optimized in a number of ways.
+
+ GenericDescriptor result;
+ String fullname;
+ if (name.startsWith(".")) {
+ // Fully-qualified name.
+ fullname = name.substring(1);
+ result = findSymbol(fullname, filter);
+ } else {
+ // If "name" is a compound identifier, we want to search for the
+ // first component of it, then search within it for the rest.
+ // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
+ // defined in multiple parent scopes, we only want to find "Bar.baz" in
+ // the innermost one. E.g., the following should produce an error:
+ // message Bar { message Baz {} }
+ // message Foo {
+ // message Bar {
+ // }
+ // optional Bar.Baz baz = 1;
+ // }
+ // So, we look for just "Foo" first, then look for "Bar.baz" within it
+ // if found.
+ final int firstPartLength = name.indexOf('.');
+ final String firstPart;
+ if (firstPartLength == -1) {
+ firstPart = name;
+ } else {
+ firstPart = name.substring(0, firstPartLength);
+ }
+
+ // We will search each parent scope of "relativeTo" looking for the
+ // symbol.
+ final StringBuilder scopeToTry =
+ new StringBuilder(relativeTo.getFullName());
+
+ while (true) {
+ // Chop off the last component of the scope.
+ final int dotpos = scopeToTry.lastIndexOf(".");
+ if (dotpos == -1) {
+ fullname = name;
+ result = findSymbol(name, filter);
+ break;
+ } else {
+ scopeToTry.setLength(dotpos + 1);
+
+ // Append firstPart and try to find
+ scopeToTry.append(firstPart);
+ result = findSymbol(scopeToTry.toString(),
+ DescriptorPool.SearchFilter.AGGREGATES_ONLY);
+
+ if (result != null) {
+ if (firstPartLength != -1) {
+ // We only found the first part of the symbol. Now look for
+ // the whole thing. If this fails, we *don't* want to keep
+ // searching parent scopes.
+ scopeToTry.setLength(dotpos + 1);
+ scopeToTry.append(name);
+ result = findSymbol(scopeToTry.toString(), filter);
+ }
+ fullname = scopeToTry.toString();
+ break;
+ }
+
+ // Not found. Remove the name so we can try again.
+ scopeToTry.setLength(dotpos);
+ }
+ }
+ }
+
+ if (result == null) {
+ if (allowUnknownDependencies && filter == SearchFilter.TYPES_ONLY) {
+ logger.warning("The descriptor for message type \"" + name +
+ "\" can not be found and a placeholder is created for it");
+ // We create a dummy message descriptor here regardless of the
+ // expected type. If the type should be message, this dummy
+ // descriptor will work well and if the type should be enum, a
+ // DescriptorValidationException will be thrown latter. In either
+ // case, the code works as expected: we allow unknown message types
+ // but not unknwon enum types.
+ result = new Descriptor(fullname);
+ // Add the placeholder file as a dependency so we can find the
+ // placeholder symbol when resolving other references.
+ this.dependencies.add(result.getFile());
+ return result;
+ } else {
+ throw new DescriptorValidationException(relativeTo,
+ '\"' + name + "\" is not defined.");
+ }
+ } else {
+ return result;
+ }
+ }
+
+ /**
+ * Adds a symbol to the symbol table. If a symbol with the same name
+ * already exists, throws an error.
+ */
+ void addSymbol(final GenericDescriptor descriptor)
+ throws DescriptorValidationException {
+ validateSymbolName(descriptor);
+
+ final String fullName = descriptor.getFullName();
+ final int dotpos = fullName.lastIndexOf('.');
+
+ final GenericDescriptor old = descriptorsByName.put(fullName, descriptor);
+ if (old != null) {
+ descriptorsByName.put(fullName, old);
+
+ if (descriptor.getFile() == old.getFile()) {
+ if (dotpos == -1) {
+ throw new DescriptorValidationException(descriptor,
+ '\"' + fullName + "\" is already defined.");
+ } else {
+ throw new DescriptorValidationException(descriptor,
+ '\"' + fullName.substring(dotpos + 1) +
+ "\" is already defined in \"" +
+ fullName.substring(0, dotpos) + "\".");
+ }
+ } else {
+ throw new DescriptorValidationException(descriptor,
+ '\"' + fullName + "\" is already defined in file \"" +
+ old.getFile().getName() + "\".");
+ }
+ }
+ }
+
+ /**
+ * Represents a package in the symbol table. We use PackageDescriptors
+ * just as placeholders so that someone cannot define, say, a message type
+ * that has the same name as an existing package.
+ */
+ private static final class PackageDescriptor extends GenericDescriptor {
+ @Override
+ public Message toProto() {
+ return file.toProto();
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
+
+ PackageDescriptor(final String name, final String fullName,
+ final FileDescriptor file) {
+ this.file = file;
+ this.fullName = fullName;
+ this.name = name;
+ }
+
+ private final String name;
+ private final String fullName;
+ private final FileDescriptor file;
+ }
+
+ /**
+ * Adds a package to the symbol tables. If a package by the same name
+ * already exists, that is fine, but if some other kind of symbol exists
+ * under the same name, an exception is thrown. If the package has
+ * multiple components, this also adds the parent package(s).
+ */
+ void addPackage(final String fullName, final FileDescriptor file)
+ throws DescriptorValidationException {
+ final int dotpos = fullName.lastIndexOf('.');
+ final String name;
+ if (dotpos == -1) {
+ name = fullName;
+ } else {
+ addPackage(fullName.substring(0, dotpos), file);
+ name = fullName.substring(dotpos + 1);
+ }
+
+ final GenericDescriptor old =
+ descriptorsByName.put(fullName,
+ new PackageDescriptor(name, fullName, file));
+ if (old != null) {
+ descriptorsByName.put(fullName, old);
+ if (!(old instanceof PackageDescriptor)) {
+ throw new DescriptorValidationException(file,
+ '\"' + name + "\" is already defined (as something other than a "
+ + "package) in file \"" + old.getFile().getName() + "\".");
+ }
+ }
+ }
+
+ /** A (GenericDescriptor, int) pair, used as a map key. */
+ private static final class DescriptorIntPair {
+ private final GenericDescriptor descriptor;
+ private final int number;
+
+ DescriptorIntPair(final GenericDescriptor descriptor, final int number) {
+ this.descriptor = descriptor;
+ this.number = number;
+ }
+
+ @Override
+ public int hashCode() {
+ return descriptor.hashCode() * ((1 << 16) - 1) + number;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof DescriptorIntPair)) {
+ return false;
+ }
+ final DescriptorIntPair other = (DescriptorIntPair)obj;
+ return descriptor == other.descriptor && number == other.number;
+ }
+ }
+
+ /**
+ * Adds a field to the fieldsByNumber table. Throws an exception if a
+ * field with the same containing type and number already exists.
+ */
+ void addFieldByNumber(final FieldDescriptor field)
+ throws DescriptorValidationException {
+ final DescriptorIntPair key =
+ new DescriptorIntPair(field.getContainingType(), field.getNumber());
+ final FieldDescriptor old = fieldsByNumber.put(key, field);
+ if (old != null) {
+ fieldsByNumber.put(key, old);
+ throw new DescriptorValidationException(field,
+ "Field number " + field.getNumber() +
+ " has already been used in \"" +
+ field.getContainingType().getFullName() +
+ "\" by field \"" + old.getName() + "\".");
+ }
+ }
+
+ /**
+ * Adds an enum value to the enumValuesByNumber table. If an enum value
+ * with the same type and number already exists, does nothing. (This is
+ * allowed; the first value define with the number takes precedence.)
+ */
+ void addEnumValueByNumber(final EnumValueDescriptor value) {
+ final DescriptorIntPair key =
+ new DescriptorIntPair(value.getType(), value.getNumber());
+ final EnumValueDescriptor old = enumValuesByNumber.put(key, value);
+ if (old != null) {
+ enumValuesByNumber.put(key, old);
+ // Not an error: Multiple enum values may have the same number, but
+ // we only want the first one in the map.
+ }
+ }
+
+ /**
+ * Verifies that the descriptor's name is valid (i.e. it contains only
+ * letters, digits, and underscores, and does not start with a digit).
+ */
+ static void validateSymbolName(final GenericDescriptor descriptor)
+ throws DescriptorValidationException {
+ final String name = descriptor.getName();
+ if (name.length() == 0) {
+ throw new DescriptorValidationException(descriptor, "Missing name.");
+ } else {
+ boolean valid = true;
+ for (int i = 0; i < name.length(); i++) {
+ final char c = name.charAt(i);
+ // Non-ASCII characters are not valid in protobuf identifiers, even
+ // if they are letters or digits.
+ if (c >= 128) {
+ valid = false;
+ }
+ // First character must be letter or _. Subsequent characters may
+ // be letters, numbers, or digits.
+ if (Character.isLetter(c) || c == '_' ||
+ (Character.isDigit(c) && i > 0)) {
+ // Valid
+ } else {
+ valid = false;
+ }
+ }
+ if (!valid) {
+ throw new DescriptorValidationException(descriptor,
+ '\"' + name + "\" is not a valid identifier.");
+ }
+ }
+ }
+ }
+
+ /** Describes an oneof of a message type. */
+ public static final class OneofDescriptor {
+ /** Get the index of this descriptor within its parent. */
+ public int getIndex() { return index; }
+
+ public String getName() { return proto.getName(); }
+
+ public FileDescriptor getFile() { return file; }
+
+ public String getFullName() { return fullName; }
+
+ public Descriptor getContainingType() { return containingType; }
+
+ public int getFieldCount() { return fieldCount; }
+
+ public OneofOptions getOptions() {
+ return proto.getOptions();
+ }
+
+ /** Get a list of this message type's fields. */
+ public List<FieldDescriptor> getFields() {
+ return Collections.unmodifiableList(Arrays.asList(fields));
+ }
+
+ public FieldDescriptor getField(int index) {
+ return fields[index];
+ }
+
+ private void setProto(final OneofDescriptorProto proto) {
+ this.proto = proto;
+ }
+
+ private OneofDescriptor(final OneofDescriptorProto proto,
+ final FileDescriptor file,
+ final Descriptor parent,
+ final int index)
+ throws DescriptorValidationException {
+ this.proto = proto;
+ fullName = computeFullName(file, parent, proto.getName());
+ this.file = file;
+ this.index = index;
+
+ containingType = parent;
+ fieldCount = 0;
+ }
+
+ private final int index;
+ private OneofDescriptorProto proto;
+ private final String fullName;
+ private final FileDescriptor file;
+
+ private Descriptor containingType;
+ private int fieldCount;
+ private FieldDescriptor[] fields;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
new file mode 100644
index 0000000000..6177f3cab9
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -0,0 +1,273 @@
+// 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 com.google.protobuf.Internal.DoubleList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link DoubleList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class DoubleArrayList
+ extends AbstractProtobufList<Double>
+ implements DoubleList, RandomAccess {
+
+ private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static DoubleArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private double[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code DoubleArrayList} with default capacity.
+ */
+ DoubleArrayList() {
+ this(new double[DEFAULT_CAPACITY], 0);
+ }
+
+ /**
+ * Constructs a new mutable {@code DoubleArrayList}
+ * containing the same elements as {@code other}.
+ */
+ private DoubleArrayList(double[] other, int size) {
+ array = other;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DoubleArrayList)) {
+ return super.equals(o);
+ }
+ DoubleArrayList other = (DoubleArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final double[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ long bits = Double.doubleToLongBits(array[i]);
+ result = (31 * result) + Internal.hashLong(bits);
+ }
+ return result;
+ }
+
+ @Override
+ public DoubleList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new DoubleArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
+ @Override
+ public Double get(int index) {
+ return getDouble(index);
+ }
+
+ @Override
+ public double getDouble(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Double set(int index, Double element) {
+ return setDouble(index, element);
+ }
+
+ @Override
+ public double setDouble(int index, double element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ double previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Double element) {
+ addDouble(index, element);
+ }
+
+ /**
+ * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addDouble(double element) {
+ addDouble(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Double)} but more efficient in that it doesn't box the element.
+ */
+ private void addDouble(int index, double element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ double[] newArray = new double[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Double> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another DoubleArrayList to avoid boxing elements.
+ if (!(collection instanceof DoubleArrayList)) {
+ return super.addAll(collection);
+ }
+
+ DoubleArrayList list = (DoubleArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Double remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ double value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
new file mode 100644
index 0000000000..e6358c3bae
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -0,0 +1,684 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An implementation of {@link Message} that can represent arbitrary types,
+ * given a {@link Descriptors.Descriptor}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class DynamicMessage extends AbstractMessage {
+ private final Descriptor type;
+ private final FieldSet<FieldDescriptor> fields;
+ private final FieldDescriptor[] oneofCases;
+ private final UnknownFieldSet unknownFields;
+ private int memoizedSize = -1;
+
+ /**
+ * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
+ * oneofCases stores the FieldDescriptor for each oneof to indicate
+ * which field is set. Caller should make sure the array is immutable.
+ *
+ * This constructor is package private and will be used in
+ * {@code DynamicMutableMessage} to convert a mutable message to an immutable
+ * message.
+ */
+ DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
+ FieldDescriptor[] oneofCases,
+ UnknownFieldSet unknownFields) {
+ this.type = type;
+ this.fields = fields;
+ this.oneofCases = oneofCases;
+ this.unknownFields = unknownFields;
+ }
+
+ /**
+ * Get a {@code DynamicMessage} representing the default instance of the
+ * given type.
+ */
+ public static DynamicMessage getDefaultInstance(Descriptor type) {
+ int oneofDeclCount = type.toProto().getOneofDeclCount();
+ FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount];
+ return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
+ oneofCases,
+ UnknownFieldSet.getDefaultInstance());
+ }
+
+
+ /** Parse a message of the given type from the given input stream. */
+ public static DynamicMessage parseFrom(Descriptor type,
+ CodedInputStream input)
+ throws IOException {
+ return newBuilder(type).mergeFrom(input).buildParsed();
+ }
+
+ /** Parse a message of the given type from the given input stream. */
+ public static DynamicMessage parseFrom(
+ Descriptor type,
+ CodedInputStream input,
+ ExtensionRegistry extensionRegistry)
+ throws IOException {
+ return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
+ }
+
+ /** Parse {@code data} as a message of the given type and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, ByteString data)
+ throws InvalidProtocolBufferException {
+ return newBuilder(type).mergeFrom(data).buildParsed();
+ }
+
+ /** Parse {@code data} as a message of the given type and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, ByteString data,
+ ExtensionRegistry extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
+ }
+
+ /** Parse {@code data} as a message of the given type and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, byte[] data)
+ throws InvalidProtocolBufferException {
+ return newBuilder(type).mergeFrom(data).buildParsed();
+ }
+
+ /** Parse {@code data} as a message of the given type and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, byte[] data,
+ ExtensionRegistry extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
+ }
+
+ /** Parse a message of the given type from {@code input} and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, InputStream input)
+ throws IOException {
+ return newBuilder(type).mergeFrom(input).buildParsed();
+ }
+
+ /** Parse a message of the given type from {@code input} and return it. */
+ public static DynamicMessage parseFrom(Descriptor type, InputStream input,
+ ExtensionRegistry extensionRegistry)
+ throws IOException {
+ return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
+ }
+
+ /** Construct a {@link Message.Builder} for the given type. */
+ public static Builder newBuilder(Descriptor type) {
+ return new Builder(type);
+ }
+
+ /**
+ * Construct a {@link Message.Builder} for a message of the same type as
+ * {@code prototype}, and initialize it with {@code prototype}'s contents.
+ */
+ public static Builder newBuilder(Message prototype) {
+ return new Builder(prototype.getDescriptorForType()).mergeFrom(prototype);
+ }
+
+ // -----------------------------------------------------------------
+ // Implementation of Message interface.
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return type;
+ }
+
+ @Override
+ public DynamicMessage getDefaultInstanceForType() {
+ return getDefaultInstance(type);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return fields.getAllFields();
+ }
+
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ verifyOneofContainingType(oneof);
+ FieldDescriptor field = oneofCases[oneof.getIndex()];
+ if (field == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ verifyOneofContainingType(oneof);
+ return oneofCases[oneof.getIndex()];
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ verifyContainingType(field);
+ return fields.hasField(field);
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ verifyContainingType(field);
+ Object result = fields.getField(field);
+ if (result == null) {
+ if (field.isRepeated()) {
+ result = Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ result = getDefaultInstance(field.getMessageType());
+ } else {
+ result = field.getDefaultValue();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ verifyContainingType(field);
+ return fields.getRepeatedFieldCount(field);
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ verifyContainingType(field);
+ return fields.getRepeatedField(field, index);
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return unknownFields;
+ }
+
+ static boolean isInitialized(Descriptor type,
+ FieldSet<FieldDescriptor> fields) {
+ // Check that all required fields are present.
+ for (final FieldDescriptor field : type.getFields()) {
+ if (field.isRequired()) {
+ if (!fields.hasField(field)) {
+ return false;
+ }
+ }
+ }
+
+ // Check that embedded messages are initialized.
+ return fields.isInitialized();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized(type, fields);
+ }
+
+ @Override
+ public void writeTo(CodedOutputStream output) throws IOException {
+ if (type.getOptions().getMessageSetWireFormat()) {
+ fields.writeMessageSetTo(output);
+ unknownFields.writeAsMessageSetTo(output);
+ } else {
+ fields.writeTo(output);
+ unknownFields.writeTo(output);
+ }
+ }
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ if (type.getOptions().getMessageSetWireFormat()) {
+ size = fields.getMessageSetSerializedSize();
+ size += unknownFields.getSerializedSizeAsMessageSet();
+ } else {
+ size = fields.getSerializedSize();
+ size += unknownFields.getSerializedSize();
+ }
+
+ memoizedSize = size;
+ return size;
+ }
+
+ @Override
+ public Builder newBuilderForType() {
+ return new Builder(type);
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return newBuilderForType().mergeFrom(this);
+ }
+
+ @Override
+ public Parser<DynamicMessage> getParserForType() {
+ return new AbstractParser<DynamicMessage>() {
+ @Override
+ public DynamicMessage parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ Builder builder = newBuilder(type);
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+ }
+
+ /** Verifies that the field is a field of this message. */
+ private void verifyContainingType(FieldDescriptor field) {
+ if (field.getContainingType() != type) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+
+ /** Verifies that the oneof is an oneof of this message. */
+ private void verifyOneofContainingType(OneofDescriptor oneof) {
+ if (oneof.getContainingType() != type) {
+ throw new IllegalArgumentException(
+ "OneofDescriptor does not match message type.");
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Builder for {@link DynamicMessage}s.
+ */
+ public static final class Builder extends AbstractMessage.Builder<Builder> {
+ private final Descriptor type;
+ private FieldSet<FieldDescriptor> fields;
+ private final FieldDescriptor[] oneofCases;
+ private UnknownFieldSet unknownFields;
+
+ /** Construct a {@code Builder} for the given type. */
+ private Builder(Descriptor type) {
+ this.type = type;
+ this.fields = FieldSet.newFieldSet();
+ this.unknownFields = UnknownFieldSet.getDefaultInstance();
+ this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
+ }
+
+ // ---------------------------------------------------------------
+ // Implementation of Message.Builder interface.
+
+ @Override
+ public Builder clear() {
+ if (fields.isImmutable()) {
+ fields = FieldSet.newFieldSet();
+ } else {
+ fields.clear();
+ }
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ return this;
+ }
+
+ @Override
+ public Builder mergeFrom(Message other) {
+ if (other instanceof DynamicMessage) {
+ // This should be somewhat faster than calling super.mergeFrom().
+ DynamicMessage otherDynamicMessage = (DynamicMessage) other;
+ if (otherDynamicMessage.type != type) {
+ throw new IllegalArgumentException(
+ "mergeFrom(Message) can only merge messages of the same type.");
+ }
+ ensureIsMutable();
+ fields.mergeFrom(otherDynamicMessage.fields);
+ mergeUnknownFields(otherDynamicMessage.unknownFields);
+ for (int i = 0; i < oneofCases.length; i++) {
+ if (oneofCases[i] == null) {
+ oneofCases[i] = otherDynamicMessage.oneofCases[i];
+ } else {
+ if ((otherDynamicMessage.oneofCases[i] != null)
+ && (oneofCases[i] != otherDynamicMessage.oneofCases[i])) {
+ fields.clearField(oneofCases[i]);
+ oneofCases[i] = otherDynamicMessage.oneofCases[i];
+ }
+ }
+ }
+ return this;
+ } else {
+ return super.mergeFrom(other);
+ }
+ }
+
+ @Override
+ public DynamicMessage build() {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ new DynamicMessage(type, fields,
+ java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields));
+ }
+ return buildPartial();
+ }
+
+ /**
+ * Helper for DynamicMessage.parseFrom() methods to call. Throws
+ * {@link InvalidProtocolBufferException} instead of
+ * {@link UninitializedMessageException}.
+ */
+ private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
+ if (!isInitialized()) {
+ throw newUninitializedMessageException(
+ new DynamicMessage(type, fields,
+ java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields))
+ .asInvalidProtocolBufferException();
+ }
+ return buildPartial();
+ }
+
+ @Override
+ public DynamicMessage buildPartial() {
+ fields.makeImmutable();
+ DynamicMessage result =
+ new DynamicMessage(type, fields,
+ java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields);
+ return result;
+ }
+
+ @Override
+ public Builder clone() {
+ Builder result = new Builder(type);
+ result.fields.mergeFrom(fields);
+ result.mergeUnknownFields(unknownFields);
+ System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length);
+ return result;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return DynamicMessage.isInitialized(type, fields);
+ }
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return type;
+ }
+
+ @Override
+ public DynamicMessage getDefaultInstanceForType() {
+ return getDefaultInstance(type);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return fields.getAllFields();
+ }
+
+ @Override
+ public Builder newBuilderForField(FieldDescriptor field) {
+ verifyContainingType(field);
+
+ if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalArgumentException(
+ "newBuilderForField is only valid for fields with message type.");
+ }
+
+ return new Builder(field.getMessageType());
+ }
+
+ @Override
+ public boolean hasOneof(OneofDescriptor oneof) {
+ verifyOneofContainingType(oneof);
+ FieldDescriptor field = oneofCases[oneof.getIndex()];
+ if (field == null) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
+ verifyOneofContainingType(oneof);
+ return oneofCases[oneof.getIndex()];
+ }
+
+ @Override
+ public Builder clearOneof(OneofDescriptor oneof) {
+ verifyOneofContainingType(oneof);
+ FieldDescriptor field = oneofCases[oneof.getIndex()];
+ if (field != null) {
+ clearField(field);
+ }
+ return this;
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ verifyContainingType(field);
+ return fields.hasField(field);
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ verifyContainingType(field);
+ Object result = fields.getField(field);
+ if (result == null) {
+ if (field.isRepeated()) {
+ result = Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ result = getDefaultInstance(field.getMessageType());
+ } else {
+ result = field.getDefaultValue();
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Builder setField(FieldDescriptor field, Object value) {
+ verifyContainingType(field);
+ ensureIsMutable();
+ // TODO(xiaofeng): This check should really be put in FieldSet.setField()
+ // where all other such checks are done. However, currently
+ // FieldSet.setField() permits Integer value for enum fields probably
+ // because of some internal features we support. Should figure it out
+ // and move this check to a more appropriate place.
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ ensureEnumValueDescriptor(field, value);
+ }
+ OneofDescriptor oneofDescriptor = field.getContainingOneof();
+ if (oneofDescriptor != null) {
+ int index = oneofDescriptor.getIndex();
+ FieldDescriptor oldField = oneofCases[index];
+ if ((oldField != null) && (oldField != field)) {
+ fields.clearField(oldField);
+ }
+ oneofCases[index] = field;
+ } else if (field.getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ if (!field.isRepeated()
+ && field.getJavaType() != FieldDescriptor.JavaType.MESSAGE
+ && value.equals(field.getDefaultValue())) {
+ // In proto3, setting a field to its default value is equivalent to clearing the field.
+ fields.clearField(field);
+ return this;
+ }
+ }
+ fields.setField(field, value);
+ return this;
+ }
+
+ @Override
+ public Builder clearField(FieldDescriptor field) {
+ verifyContainingType(field);
+ ensureIsMutable();
+ OneofDescriptor oneofDescriptor = field.getContainingOneof();
+ if (oneofDescriptor != null) {
+ int index = oneofDescriptor.getIndex();
+ if (oneofCases[index] == field) {
+ oneofCases[index] = null;
+ }
+ }
+ fields.clearField(field);
+ return this;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ verifyContainingType(field);
+ return fields.getRepeatedFieldCount(field);
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ verifyContainingType(field);
+ return fields.getRepeatedField(field, index);
+ }
+
+ @Override
+ public Builder setRepeatedField(FieldDescriptor field, int index, Object value) {
+ verifyContainingType(field);
+ ensureIsMutable();
+ fields.setRepeatedField(field, index, value);
+ return this;
+ }
+
+ @Override
+ public Builder addRepeatedField(FieldDescriptor field, Object value) {
+ verifyContainingType(field);
+ ensureIsMutable();
+ fields.addRepeatedField(field, value);
+ return this;
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return unknownFields;
+ }
+
+ @Override
+ public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+ if (getDescriptorForType().getFile().getSyntax()
+ == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ // Proto3 discards unknown fields.
+ return this;
+ }
+ this.unknownFields = unknownFields;
+ return this;
+ }
+
+ @Override
+ public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
+ if (getDescriptorForType().getFile().getSyntax()
+ == Descriptors.FileDescriptor.Syntax.PROTO3) {
+ // Proto3 discards unknown fields.
+ return this;
+ }
+ this.unknownFields =
+ UnknownFieldSet.newBuilder(this.unknownFields)
+ .mergeFrom(unknownFields)
+ .build();
+ return this;
+ }
+
+ /** Verifies that the field is a field of this message. */
+ private void verifyContainingType(FieldDescriptor field) {
+ if (field.getContainingType() != type) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+
+ /** Verifies that the oneof is an oneof of this message. */
+ private void verifyOneofContainingType(OneofDescriptor oneof) {
+ if (oneof.getContainingType() != type) {
+ throw new IllegalArgumentException(
+ "OneofDescriptor does not match message type.");
+ }
+ }
+
+ /** Verifies that the value is EnumValueDescriptor and matches Enum Type. */
+ private void ensureSingularEnumValueDescriptor(
+ FieldDescriptor field, Object value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ if (!(value instanceof EnumValueDescriptor)) {
+ throw new IllegalArgumentException(
+ "DynamicMessage should use EnumValueDescriptor to set Enum Value.");
+ }
+ // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
+ // set incorrect EnumValueDescriptors.
+ // EnumDescriptor fieldType = field.getEnumType();
+ // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType();
+ // if (fieldType != fieldValueType) {
+ // throw new IllegalArgumentException(String.format(
+ // "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value",
+ // fieldType.getFullName(), fieldValueType.getFullName()));
+ // }
+ }
+
+ /** Verifies the value for an enum field. */
+ private void ensureEnumValueDescriptor(
+ FieldDescriptor field, Object value) {
+ if (field.isRepeated()) {
+ for (Object item : (List) value) {
+ ensureSingularEnumValueDescriptor(field, item);
+ }
+ } else {
+ ensureSingularEnumValueDescriptor(field, value);
+ }
+ }
+
+ private void ensureIsMutable() {
+ if (fields.isImmutable()) {
+ fields = fields.clone();
+ }
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
+ // TODO(xiangl): need implementation for dynamic message
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a dynamic message type.");
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedFieldBuilder(FieldDescriptor field,
+ int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a dynamic message type.");
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
new file mode 100644
index 0000000000..3cd4c88492
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExperimentalApi.java
@@ -0,0 +1,66 @@
+// 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.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/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Extension.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Extension.java
new file mode 100644
index 0000000000..08ec5b4541
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Extension.java
@@ -0,0 +1,86 @@
+// 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;
+
+/**
+ * Interface that generated extensions implement.
+ *
+ * @author liujisi@google.com (Jisi Liu)
+ */
+public abstract class Extension<ContainingType extends MessageLite, Type>
+ extends ExtensionLite<ContainingType, Type> {
+
+ /** Returns the descriptor of the extension. */
+ public abstract Descriptors.FieldDescriptor getDescriptor();
+
+ /** Returns whether or not this extension is a Lite Extension. */
+ @Override
+ final boolean isLite() {
+ return false;
+ }
+
+ // All the methods below are extension implementation details.
+
+ /**
+ * The API type that the extension is used for.
+ */
+ protected enum ExtensionType {
+ IMMUTABLE,
+ MUTABLE,
+ PROTO1,
+ }
+
+ protected ExtensionType getExtensionType() {
+ // TODO(liujisi): make this abstract after we fix proto1.
+ return ExtensionType.IMMUTABLE;
+ }
+
+ /**
+ * Type of a message extension.
+ */
+ public enum MessageType {
+ PROTO1,
+ PROTO2,
+ }
+
+ /**
+ * If the extension is a message extension (i.e., getLiteType() == MESSAGE),
+ * returns the type of the message, otherwise undefined.
+ */
+ public MessageType getMessageType() {
+ return MessageType.PROTO2;
+ }
+
+ protected abstract Object fromReflectionType(Object value);
+ protected abstract Object singularFromReflectionType(Object value);
+ protected abstract Object toReflectionType(Object value);
+ protected abstract Object singularToReflectionType(Object value);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionLite.java
new file mode 100644
index 0000000000..f8f5bd2c4f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionLite.java
@@ -0,0 +1,63 @@
+// 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;
+
+/**
+ * Lite interface that generated extensions implement.
+ * <p>
+ * Methods are for use by generated code only. You can hold a reference to
+ * extensions using this type name.
+ */
+public abstract class ExtensionLite<ContainingType extends MessageLite, Type> {
+
+ /** Returns the field number of the extension. */
+ public abstract int getNumber();
+
+ /** Returns the type of the field. */
+ public abstract WireFormat.FieldType getLiteType();
+
+ /** Returns whether it is a repeated field. */
+ public abstract boolean isRepeated();
+
+ /** Returns the default value of the extension field. */
+ public abstract Type getDefaultValue();
+
+ /**
+ * Returns the default instance of the extension field, if it's a message
+ * extension.
+ */
+ public abstract MessageLite getMessageDefaultInstance();
+
+ /** Returns whether or not this extension is a Lite Extension. */
+ boolean isLite() {
+ return true;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
new file mode 100644
index 0000000000..a22a74a03c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -0,0 +1,396 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A table of known extensions, searchable by name or field number. When
+ * parsing a protocol message that might have extensions, you must provide
+ * an {@code ExtensionRegistry} in which you have registered any extensions
+ * that you want to be able to parse. Otherwise, those extensions will just
+ * be treated like unknown fields.
+ *
+ * <p>For example, if you had the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * Then you might write code like:
+ *
+ * <pre>
+ * ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ * registry.add(MyProto.bar);
+ * MyProto.Foo message = MyProto.Foo.parseFrom(input, registry);
+ * </pre>
+ *
+ * <p>Background:
+ *
+ * <p>You might wonder why this is necessary. Two alternatives might come to
+ * mind. First, you might imagine a system where generated extensions are
+ * automatically registered when their containing classes are loaded. This
+ * is a popular technique, but is bad design; among other things, it creates a
+ * situation where behavior can change depending on what classes happen to be
+ * loaded. It also introduces a security vulnerability, because an
+ * unprivileged class could cause its code to be called unexpectedly from a
+ * privileged class by registering itself as an extension of the right type.
+ *
+ * <p>Another option you might consider is lazy parsing: do not parse an
+ * extension until it is first requested, at which point the caller must
+ * provide a type to use. This introduces a different set of problems. First,
+ * it would require a mutex lock any time an extension was accessed, which
+ * would be slow. Second, corrupt data would not be detected until first
+ * access, at which point it would be much harder to deal with it. Third, it
+ * could violate the expectation that message objects are immutable, since the
+ * type provided could be any arbitrary message class. An unprivileged user
+ * could take advantage of this to inject a mutable object into a message
+ * belonging to privileged code and create mischief.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistry extends ExtensionRegistryLite {
+ /** Construct a new, empty instance. */
+ public static ExtensionRegistry newInstance() {
+ return new ExtensionRegistry();
+ }
+
+ /** Get the unmodifiable singleton empty instance. */
+ public static ExtensionRegistry getEmptyRegistry() {
+ return EMPTY_REGISTRY;
+ }
+
+
+ /** Returns an unmodifiable view of the registry. */
+ @Override
+ public ExtensionRegistry getUnmodifiable() {
+ return new ExtensionRegistry(this);
+ }
+
+ /** A (Descriptor, Message) pair, returned by lookup methods. */
+ public static final class ExtensionInfo {
+ /** The extension's descriptor. */
+ public final FieldDescriptor descriptor;
+
+ /**
+ * A default instance of the extension's type, if it has a message type.
+ * Otherwise, {@code null}.
+ */
+ public final Message defaultInstance;
+
+ private ExtensionInfo(final FieldDescriptor descriptor) {
+ this.descriptor = descriptor;
+ defaultInstance = null;
+ }
+ private ExtensionInfo(final FieldDescriptor descriptor,
+ final Message defaultInstance) {
+ this.descriptor = descriptor;
+ this.defaultInstance = defaultInstance;
+ }
+ }
+
+ /**
+ * Deprecated. Use {@link #findImmutableExtensionByName(String)} instead.
+ */
+ public ExtensionInfo findExtensionByName(final String fullName) {
+ return findImmutableExtensionByName(fullName);
+ }
+
+ /**
+ * Find an extension for immutable APIs by fully-qualified field name,
+ * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
+ * match {@code fullName} if a match is found.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ public ExtensionInfo findImmutableExtensionByName(final String fullName) {
+ return immutableExtensionsByName.get(fullName);
+ }
+
+ /**
+ * Find an extension for mutable APIs by fully-qualified field name,
+ * in the proto namespace. i.e. {@code result.descriptor.fullName()} will
+ * match {@code fullName} if a match is found.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ public ExtensionInfo findMutableExtensionByName(final String fullName) {
+ return mutableExtensionsByName.get(fullName);
+ }
+
+ /**
+ * Deprecated. Use {@link #findImmutableExtensionByNumber(
+ * Descriptors.Descriptor, int)}
+ */
+ public ExtensionInfo findExtensionByNumber(
+ final Descriptor containingType, final int fieldNumber) {
+ return findImmutableExtensionByNumber(containingType, fieldNumber);
+ }
+
+ /**
+ * Find an extension by containing type and field number for immutable APIs.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ public ExtensionInfo findImmutableExtensionByNumber(
+ final Descriptor containingType, final int fieldNumber) {
+ return immutableExtensionsByNumber.get(
+ new DescriptorIntPair(containingType, fieldNumber));
+ }
+
+ /**
+ * Find an extension by containing type and field number for mutable APIs.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ public ExtensionInfo findMutableExtensionByNumber(
+ final Descriptor containingType, final int fieldNumber) {
+ return mutableExtensionsByNumber.get(
+ new DescriptorIntPair(containingType, fieldNumber));
+ }
+
+ /**
+ * Find all extensions for mutable APIs by fully-qualified name of
+ * extended class. Note that this method is more computationally expensive
+ * than getting a single extension by name or number.
+ *
+ * @return Information about the extensions found, or {@code null} if there
+ * are none.
+ */
+ public Set<ExtensionInfo> getAllMutableExtensionsByExtendedType(final String fullName) {
+ HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+ for (DescriptorIntPair pair : mutableExtensionsByNumber.keySet()) {
+ if (pair.descriptor.getFullName().equals(fullName)) {
+ extensions.add(mutableExtensionsByNumber.get(pair));
+ }
+ }
+ return extensions;
+ }
+
+ /**
+ * Find all extensions for immutable APIs by fully-qualified name of
+ * extended class. Note that this method is more computationally expensive
+ * than getting a single extension by name or number.
+ *
+ * @return Information about the extensions found, or {@code null} if there
+ * are none.
+ */
+ public Set<ExtensionInfo> getAllImmutableExtensionsByExtendedType(final String fullName) {
+ HashSet<ExtensionInfo> extensions = new HashSet<ExtensionInfo>();
+ for (DescriptorIntPair pair : immutableExtensionsByNumber.keySet()) {
+ if (pair.descriptor.getFullName().equals(fullName)) {
+ extensions.add(immutableExtensionsByNumber.get(pair));
+ }
+ }
+ return extensions;
+ }
+
+ /** Add an extension from a generated file to the registry. */
+ public void add(final Extension<?, ?> extension) {
+ if (extension.getExtensionType() != Extension.ExtensionType.IMMUTABLE &&
+ extension.getExtensionType() != Extension.ExtensionType.MUTABLE) {
+ // do not support other extension types. ignore
+ return;
+ }
+ add(newExtensionInfo(extension), extension.getExtensionType());
+ }
+
+ /** Add an extension from a generated file to the registry. */
+ public void add(final GeneratedMessage.GeneratedExtension<?, ?> extension) {
+ add((Extension<?, ?>) extension);
+ }
+
+ static ExtensionInfo newExtensionInfo(final Extension<?, ?> extension) {
+ if (extension.getDescriptor().getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ if (extension.getMessageDefaultInstance() == null) {
+ throw new IllegalStateException(
+ "Registered message-type extension had null default instance: " +
+ extension.getDescriptor().getFullName());
+ }
+ return new ExtensionInfo(extension.getDescriptor(),
+ (Message) extension.getMessageDefaultInstance());
+ } else {
+ return new ExtensionInfo(extension.getDescriptor(), null);
+ }
+ }
+
+ /** Add a non-message-type extension to the registry by descriptor. */
+ public void add(final FieldDescriptor type) {
+ if (type.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalArgumentException(
+ "ExtensionRegistry.add() must be provided a default instance when " +
+ "adding an embedded message extension.");
+ }
+ ExtensionInfo info = new ExtensionInfo(type, null);
+ add(info, Extension.ExtensionType.IMMUTABLE);
+ add(info, Extension.ExtensionType.MUTABLE);
+ }
+
+ /** Add a message-type extension to the registry by descriptor. */
+ public void add(final FieldDescriptor type, final Message defaultInstance) {
+ if (type.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalArgumentException(
+ "ExtensionRegistry.add() provided a default instance for a " +
+ "non-message extension.");
+ }
+ add(new ExtensionInfo(type, defaultInstance),
+ Extension.ExtensionType.IMMUTABLE);
+ }
+
+ // =================================================================
+ // Private stuff.
+
+ private ExtensionRegistry() {
+ this.immutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+ this.mutableExtensionsByName = new HashMap<String, ExtensionInfo>();
+ this.immutableExtensionsByNumber =
+ new HashMap<DescriptorIntPair, ExtensionInfo>();
+ this.mutableExtensionsByNumber =
+ new HashMap<DescriptorIntPair, ExtensionInfo>();
+ }
+
+ private ExtensionRegistry(ExtensionRegistry other) {
+ super(other);
+ this.immutableExtensionsByName =
+ Collections.unmodifiableMap(other.immutableExtensionsByName);
+ this.mutableExtensionsByName =
+ Collections.unmodifiableMap(other.mutableExtensionsByName);
+ this.immutableExtensionsByNumber =
+ Collections.unmodifiableMap(other.immutableExtensionsByNumber);
+ this.mutableExtensionsByNumber =
+ Collections.unmodifiableMap(other.mutableExtensionsByNumber);
+ }
+
+ private final Map<String, ExtensionInfo> immutableExtensionsByName;
+ private final Map<String, ExtensionInfo> mutableExtensionsByName;
+ private final Map<DescriptorIntPair, ExtensionInfo> immutableExtensionsByNumber;
+ private final Map<DescriptorIntPair, ExtensionInfo> mutableExtensionsByNumber;
+
+ ExtensionRegistry(boolean empty) {
+ super(EMPTY_REGISTRY_LITE);
+ this.immutableExtensionsByName =
+ Collections.<String, ExtensionInfo>emptyMap();
+ this.mutableExtensionsByName =
+ Collections.<String, ExtensionInfo>emptyMap();
+ this.immutableExtensionsByNumber =
+ Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+ this.mutableExtensionsByNumber =
+ Collections.<DescriptorIntPair, ExtensionInfo>emptyMap();
+ }
+ static final ExtensionRegistry EMPTY_REGISTRY = new ExtensionRegistry(true);
+
+ private void add(
+ final ExtensionInfo extension,
+ final Extension.ExtensionType extensionType) {
+ if (!extension.descriptor.isExtension()) {
+ throw new IllegalArgumentException(
+ "ExtensionRegistry.add() was given a FieldDescriptor for a regular " +
+ "(non-extension) field.");
+ }
+
+ Map<String, ExtensionInfo> extensionsByName;
+ Map<DescriptorIntPair, ExtensionInfo> extensionsByNumber;
+ switch (extensionType) {
+ case IMMUTABLE:
+ extensionsByName = immutableExtensionsByName;
+ extensionsByNumber = immutableExtensionsByNumber;
+ break;
+ case MUTABLE:
+ extensionsByName = mutableExtensionsByName;
+ extensionsByNumber = mutableExtensionsByNumber;
+ break;
+ default:
+ // Ignore the unknown supported type.
+ return;
+ }
+
+ extensionsByName.put(extension.descriptor.getFullName(), extension);
+ extensionsByNumber.put(
+ new DescriptorIntPair(extension.descriptor.getContainingType(),
+ extension.descriptor.getNumber()),
+ extension);
+
+ final FieldDescriptor field = extension.descriptor;
+ if (field.getContainingType().getOptions().getMessageSetWireFormat() &&
+ field.getType() == FieldDescriptor.Type.MESSAGE &&
+ field.isOptional() &&
+ field.getExtensionScope() == field.getMessageType()) {
+ // This is an extension of a MessageSet type defined within the extension
+ // type's own scope. For backwards-compatibility, allow it to be looked
+ // up by type name.
+ extensionsByName.put(field.getMessageType().getFullName(), extension);
+ }
+ }
+
+ /** A (GenericDescriptor, int) pair, used as a map key. */
+ private static final class DescriptorIntPair {
+ private final Descriptor descriptor;
+ private final int number;
+
+ DescriptorIntPair(final Descriptor descriptor, final int number) {
+ this.descriptor = descriptor;
+ this.number = number;
+ }
+
+ @Override
+ public int hashCode() {
+ return descriptor.hashCode() * ((1 << 16) - 1) + number;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof DescriptorIntPair)) {
+ return false;
+ }
+ final DescriptorIntPair other = (DescriptorIntPair)obj;
+ return descriptor == other.descriptor && number == other.number;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
new file mode 100644
index 0000000000..23174e24c7
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
@@ -0,0 +1,95 @@
+// 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 static com.google.protobuf.ExtensionRegistryLite.EMPTY_REGISTRY_LITE;
+
+/**
+ * A factory object to create instances of {@link ExtensionRegistryLite}.
+ *
+ * <p>
+ * This factory detects (via reflection) if the full (non-Lite) protocol buffer libraries
+ * are available, and if so, the instances returned are actually {@link ExtensionRegistry}.
+ */
+final class ExtensionRegistryFactory {
+
+ static final String FULL_REGISTRY_CLASS_NAME = "com.google.protobuf.ExtensionRegistry";
+
+ /* Visible for Testing
+ @Nullable */
+ static final Class<?> EXTENSION_REGISTRY_CLASS = reflectExtensionRegistry();
+
+ /* @Nullable */
+ static Class<?> reflectExtensionRegistry() {
+ try {
+ return Class.forName(FULL_REGISTRY_CLASS_NAME);
+ } catch (ClassNotFoundException e) {
+ // The exception allocation is potentially expensive on Android (where it can be triggered
+ // many times at start up). Is there a way to ameliorate this?
+ return null;
+ }
+ }
+
+ /** Construct a new, empty instance. */
+ public static ExtensionRegistryLite create() {
+ if (EXTENSION_REGISTRY_CLASS != null) {
+ try {
+ return invokeSubclassFactory("newInstance");
+ } catch (Exception e) {
+ // return a Lite registry.
+ }
+ }
+ return new ExtensionRegistryLite();
+ }
+
+ /** Get the unmodifiable singleton empty instance. */
+ public static ExtensionRegistryLite createEmpty() {
+ if (EXTENSION_REGISTRY_CLASS != null) {
+ try {
+ return invokeSubclassFactory("getEmptyRegistry");
+ } catch (Exception e) {
+ // return a Lite registry.
+ }
+ }
+ return EMPTY_REGISTRY_LITE;
+ }
+
+ static boolean isFullRegistry(ExtensionRegistryLite registry) {
+ return EXTENSION_REGISTRY_CLASS != null
+ && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass());
+ }
+
+ private static final ExtensionRegistryLite invokeSubclassFactory(String methodName)
+ throws Exception {
+ return (ExtensionRegistryLite) EXTENSION_REGISTRY_CLASS
+ .getMethod(methodName).invoke(null);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
new file mode 100644
index 0000000000..f3d48d3af3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -0,0 +1,227 @@
+// 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.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Equivalent to {@link ExtensionRegistry} but supports only "lite" types.
+ * <p>
+ * If all of your types are lite types, then you only need to use
+ * {@code ExtensionRegistryLite}. Similarly, if all your types are regular
+ * types, then you only need {@link ExtensionRegistry}. Typically it does not
+ * make sense to mix the two, since if you have any regular types in your
+ * program, you then require the full runtime and lose all the benefits of
+ * the lite runtime, so you might as well make all your types be regular types.
+ * However, in some cases (e.g. when depending on multiple third-party libraries
+ * where one uses lite types and one uses regular), you may find yourself
+ * wanting to mix the two. In this case things get more complicated.
+ * <p>
+ * There are three factors to consider: Whether the type being extended is
+ * lite, whether the embedded type (in the case of a message-typed extension)
+ * is lite, and whether the extension itself is lite. Since all three are
+ * declared in different files, they could all be different. Here are all
+ * the combinations and which type of registry to use:
+ * <pre>
+ * Extended type Inner type Extension Use registry
+ * =======================================================================
+ * lite lite lite ExtensionRegistryLite
+ * lite regular lite ExtensionRegistry
+ * regular regular regular ExtensionRegistry
+ * all other combinations not supported
+ * </pre>
+ * <p>
+ * Note that just as regular types are not allowed to contain lite-type fields,
+ * they are also not allowed to contain lite-type extensions. This is because
+ * regular types must be fully accessible via reflection, which in turn means
+ * that all the inner messages must also support reflection. On the other hand,
+ * since regular types implement the entire lite interface, there is no problem
+ * with embedding regular types inside lite types.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ExtensionRegistryLite {
+
+ // Set true to enable lazy parsing feature for MessageSet.
+ //
+ // TODO(xiangl): Now we use a global flag to control whether enable lazy
+ // parsing feature for MessageSet, which may be too crude for some
+ // applications. Need to support this feature on smaller granularity.
+ private static volatile boolean eagerlyParseMessageSets = false;
+
+ // Visible for testing.
+ static final String EXTENSION_CLASS_NAME = "com.google.protobuf.Extension";
+
+ /* @Nullable */
+ static Class<?> resolveExtensionClass() {
+ try {
+ return Class.forName(EXTENSION_CLASS_NAME);
+ } catch (ClassNotFoundException e) {
+ // See comment in ExtensionRegistryFactory on the potential expense of this.
+ return null;
+ }
+ }
+
+ /* @Nullable */
+ private static final Class<?> extensionClass = resolveExtensionClass();
+
+ public static boolean isEagerlyParseMessageSets() {
+ return eagerlyParseMessageSets;
+ }
+
+ public static void setEagerlyParseMessageSets(boolean isEagerlyParse) {
+ eagerlyParseMessageSets = isEagerlyParse;
+ }
+
+ /**
+ * Construct a new, empty instance.
+ *
+ * <p>This may be an {@code ExtensionRegistry} if the full (non-Lite) proto libraries are
+ * available.
+ */
+ public static ExtensionRegistryLite newInstance() {
+ return ExtensionRegistryFactory.create();
+ }
+
+ /**
+ * Get the unmodifiable singleton empty instance of either ExtensionRegistryLite or
+ * {@code ExtensionRegistry} (if the full (non-Lite) proto libraries are available).
+ */
+ public static ExtensionRegistryLite getEmptyRegistry() {
+ return ExtensionRegistryFactory.createEmpty();
+ }
+
+
+ /** Returns an unmodifiable view of the registry. */
+ public ExtensionRegistryLite getUnmodifiable() {
+ return new ExtensionRegistryLite(this);
+ }
+
+ /**
+ * Find an extension by containing type and field number.
+ *
+ * @return Information about the extension if found, or {@code null}
+ * otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ public <ContainingType extends MessageLite>
+ GeneratedMessageLite.GeneratedExtension<ContainingType, ?>
+ findLiteExtensionByNumber(
+ final ContainingType containingTypeDefaultInstance,
+ final int fieldNumber) {
+ return (GeneratedMessageLite.GeneratedExtension<ContainingType, ?>)
+ extensionsByNumber.get(
+ new ObjectIntPair(containingTypeDefaultInstance, fieldNumber));
+ }
+
+ /** Add an extension from a lite generated file to the registry. */
+ public final void add(
+ final GeneratedMessageLite.GeneratedExtension<?, ?> extension) {
+ extensionsByNumber.put(
+ new ObjectIntPair(extension.getContainingTypeDefaultInstance(),
+ extension.getNumber()),
+ extension);
+ }
+
+ /**
+ * Add an extension from a lite generated file to the registry only if it is
+ * a non-lite extension i.e. {@link GeneratedMessageLite.GeneratedExtension}. */
+ public final void add(ExtensionLite<?, ?> extension) {
+ if (GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(extension.getClass())) {
+ add((GeneratedMessageLite.GeneratedExtension<?, ?>) extension);
+ }
+ if (ExtensionRegistryFactory.isFullRegistry(this)) {
+ try {
+ this.getClass().getMethod("add", extensionClass).invoke(this, extension);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ String.format("Could not invoke ExtensionRegistry#add for %s", extension), e);
+ }
+ }
+ }
+
+ // =================================================================
+ // Private stuff.
+
+ // Constructors are package-private so that ExtensionRegistry can subclass
+ // this.
+
+ ExtensionRegistryLite() {
+ this.extensionsByNumber =
+ new HashMap<ObjectIntPair,
+ GeneratedMessageLite.GeneratedExtension<?, ?>>();
+ }
+ static final ExtensionRegistryLite EMPTY_REGISTRY_LITE =
+ new ExtensionRegistryLite(true);
+
+ ExtensionRegistryLite(ExtensionRegistryLite other) {
+ if (other == EMPTY_REGISTRY_LITE) {
+ this.extensionsByNumber = Collections.emptyMap();
+ } else {
+ this.extensionsByNumber =
+ Collections.unmodifiableMap(other.extensionsByNumber);
+ }
+ }
+
+ private final Map<ObjectIntPair,
+ GeneratedMessageLite.GeneratedExtension<?, ?>>
+ extensionsByNumber;
+
+ ExtensionRegistryLite(boolean empty) {
+ this.extensionsByNumber = Collections.emptyMap();
+ }
+
+ /** A (Object, int) pair, used as a map key. */
+ private static final class ObjectIntPair {
+ private final Object object;
+ private final int number;
+
+ ObjectIntPair(final Object object, final int number) {
+ this.object = object;
+ this.number = number;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(object) * ((1 << 16) - 1) + number;
+ }
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof ObjectIntPair)) {
+ return false;
+ }
+ final ObjectIntPair other = (ObjectIntPair)obj;
+ return object == other.object && number == other.number;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FieldSet.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FieldSet.java
new file mode 100644
index 0000000000..a828f30edb
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -0,0 +1,909 @@
+// 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 com.google.protobuf.LazyField.LazyIterator;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class which represents an arbitrary set of fields of some message type.
+ * This is used to implement {@link DynamicMessage}, and also to represent
+ * extensions in {@link GeneratedMessage}. This class is package-private,
+ * since outside users should probably be using {@link DynamicMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+final class FieldSet<FieldDescriptorType extends
+ FieldSet.FieldDescriptorLite<FieldDescriptorType>> {
+ /**
+ * Interface for a FieldDescriptor or lite extension descriptor. This
+ * prevents FieldSet from depending on {@link Descriptors.FieldDescriptor}.
+ */
+ public interface FieldDescriptorLite<T extends FieldDescriptorLite<T>>
+ extends Comparable<T> {
+ int getNumber();
+ WireFormat.FieldType getLiteType();
+ WireFormat.JavaType getLiteJavaType();
+ boolean isRepeated();
+ boolean isPacked();
+ Internal.EnumLiteMap<?> getEnumType();
+
+ // If getLiteJavaType() == MESSAGE, this merges a message object of the
+ // type into a builder of the type. Returns {@code to}.
+ MessageLite.Builder internalMergeFrom(
+ MessageLite.Builder to, MessageLite from);
+ }
+
+ private final SmallSortedMap<FieldDescriptorType, Object> fields;
+ private boolean isImmutable;
+ private boolean hasLazyField = false;
+
+ /** Construct a new FieldSet. */
+ private FieldSet() {
+ this.fields = SmallSortedMap.newFieldMap(16);
+ }
+
+ /**
+ * Construct an empty FieldSet. This is only used to initialize
+ * DEFAULT_INSTANCE.
+ */
+ private FieldSet(final boolean dummy) {
+ this.fields = SmallSortedMap.newFieldMap(0);
+ makeImmutable();
+ }
+
+ /** Construct a new FieldSet. */
+ public static <T extends FieldSet.FieldDescriptorLite<T>>
+ FieldSet<T> newFieldSet() {
+ return new FieldSet<T>();
+ }
+
+ /** Get an immutable empty FieldSet. */
+ @SuppressWarnings("unchecked")
+ public static <T extends FieldSet.FieldDescriptorLite<T>>
+ FieldSet<T> emptySet() {
+ return DEFAULT_INSTANCE;
+ }
+ @SuppressWarnings("rawtypes")
+ private static final FieldSet DEFAULT_INSTANCE = new FieldSet(true);
+
+ /** Make this FieldSet immutable from this point forward. */
+ @SuppressWarnings("unchecked")
+ public void makeImmutable() {
+ if (isImmutable) {
+ return;
+ }
+ fields.makeImmutable();
+ isImmutable = true;
+ }
+
+ /**
+ * Returns whether the FieldSet is immutable. This is true if it is the
+ * {@link #emptySet} or if {@link #makeImmutable} were called.
+ *
+ * @return whether the FieldSet is immutable.
+ */
+ public boolean isImmutable() {
+ return isImmutable;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof FieldSet)) {
+ return false;
+ }
+
+ FieldSet<?> other = (FieldSet<?>) o;
+ return fields.equals(other.fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return fields.hashCode();
+ }
+
+ /**
+ * Clones the FieldSet. The returned FieldSet will be mutable even if the
+ * original FieldSet was immutable.
+ *
+ * @return the newly cloned FieldSet
+ */
+ @Override
+ public FieldSet<FieldDescriptorType> clone() {
+ // We can't just call fields.clone because List objects in the map
+ // should not be shared.
+ FieldSet<FieldDescriptorType> clone = FieldSet.newFieldSet();
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ Map.Entry<FieldDescriptorType, Object> entry = fields.getArrayEntryAt(i);
+ FieldDescriptorType descriptor = entry.getKey();
+ clone.setField(descriptor, entry.getValue());
+ }
+ for (Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ FieldDescriptorType descriptor = entry.getKey();
+ clone.setField(descriptor, entry.getValue());
+ }
+ clone.hasLazyField = hasLazyField;
+ return clone;
+ }
+
+
+ // =================================================================
+
+ /** See {@link Message.Builder#clear()}. */
+ public void clear() {
+ fields.clear();
+ hasLazyField = false;
+ }
+
+ /**
+ * Get a simple map containing all the fields.
+ */
+ public Map<FieldDescriptorType, Object> getAllFields() {
+ if (hasLazyField) {
+ SmallSortedMap<FieldDescriptorType, Object> result =
+ SmallSortedMap.newFieldMap(16);
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ cloneFieldEntry(result, fields.getArrayEntryAt(i));
+ }
+ for (Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ cloneFieldEntry(result, entry);
+ }
+ if (fields.isImmutable()) {
+ result.makeImmutable();
+ }
+ return result;
+ }
+ return fields.isImmutable() ? fields : Collections.unmodifiableMap(fields);
+ }
+
+ private void cloneFieldEntry(Map<FieldDescriptorType, Object> map,
+ Map.Entry<FieldDescriptorType, Object> entry) {
+ FieldDescriptorType key = entry.getKey();
+ Object value = entry.getValue();
+ if (value instanceof LazyField) {
+ map.put(key, ((LazyField) value).getValue());
+ } else {
+ map.put(key, value);
+ }
+ }
+
+ /**
+ * Get an iterator to the field map. This iterator should not be leaked out
+ * of the protobuf library as it is not protected from mutation when fields
+ * is not immutable.
+ */
+ public Iterator<Map.Entry<FieldDescriptorType, Object>> iterator() {
+ if (hasLazyField) {
+ return new LazyIterator<FieldDescriptorType>(
+ fields.entrySet().iterator());
+ }
+ return fields.entrySet().iterator();
+ }
+
+
+ /**
+ * Useful for implementing
+ * {@link Message#hasField(Descriptors.FieldDescriptor)}.
+ */
+ public boolean hasField(final FieldDescriptorType descriptor) {
+ if (descriptor.isRepeated()) {
+ throw new IllegalArgumentException(
+ "hasField() can only be called on non-repeated fields.");
+ }
+
+ return fields.get(descriptor) != null;
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message#getField(Descriptors.FieldDescriptor)}. This method
+ * returns {@code null} if the field is not set; in this case it is up
+ * to the caller to fetch the field's default value.
+ */
+ public Object getField(final FieldDescriptorType descriptor) {
+ Object o = fields.get(descriptor);
+ if (o instanceof LazyField) {
+ return ((LazyField) o).getValue();
+ }
+ return o;
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public void setField(final FieldDescriptorType descriptor,
+ Object value) {
+ if (descriptor.isRepeated()) {
+ if (!(value instanceof List)) {
+ throw new IllegalArgumentException(
+ "Wrong object type used with protocol message reflection.");
+ }
+
+ // Wrap the contents in a new list so that the caller cannot change
+ // the list's contents after setting it.
+ final List newList = new ArrayList();
+ newList.addAll((List) value);
+ for (final Object element : newList) {
+ verifyType(descriptor.getLiteType(), element);
+ }
+ value = newList;
+ } else {
+ verifyType(descriptor.getLiteType(), value);
+ }
+
+ if (value instanceof LazyField) {
+ hasLazyField = true;
+ }
+ fields.put(descriptor, value);
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#clearField(Descriptors.FieldDescriptor)}.
+ */
+ public void clearField(final FieldDescriptorType descriptor) {
+ fields.remove(descriptor);
+ if (fields.isEmpty()) {
+ hasLazyField = false;
+ }
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message#getRepeatedFieldCount(Descriptors.FieldDescriptor)}.
+ */
+ public int getRepeatedFieldCount(final FieldDescriptorType descriptor) {
+ if (!descriptor.isRepeated()) {
+ throw new IllegalArgumentException(
+ "getRepeatedField() can only be called on repeated fields.");
+ }
+
+ final Object value = getField(descriptor);
+ if (value == null) {
+ return 0;
+ } else {
+ return ((List<?>) value).size();
+ }
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)}.
+ */
+ public Object getRepeatedField(final FieldDescriptorType descriptor,
+ final int index) {
+ if (!descriptor.isRepeated()) {
+ throw new IllegalArgumentException(
+ "getRepeatedField() can only be called on repeated fields.");
+ }
+
+ final Object value = getField(descriptor);
+
+ if (value == null) {
+ throw new IndexOutOfBoundsException();
+ } else {
+ return ((List<?>) value).get(index);
+ }
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#setRepeatedField(Descriptors.FieldDescriptor,int,Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ public void setRepeatedField(final FieldDescriptorType descriptor,
+ final int index,
+ final Object value) {
+ if (!descriptor.isRepeated()) {
+ throw new IllegalArgumentException(
+ "getRepeatedField() can only be called on repeated fields.");
+ }
+
+ final Object list = getField(descriptor);
+ if (list == null) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ verifyType(descriptor.getLiteType(), value);
+ ((List<Object>) list).set(index, value);
+ }
+
+ /**
+ * Useful for implementing
+ * {@link Message.Builder#addRepeatedField(Descriptors.FieldDescriptor,Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ public void addRepeatedField(final FieldDescriptorType descriptor,
+ final Object value) {
+ if (!descriptor.isRepeated()) {
+ throw new IllegalArgumentException(
+ "addRepeatedField() can only be called on repeated fields.");
+ }
+
+ verifyType(descriptor.getLiteType(), value);
+
+ final Object existingValue = getField(descriptor);
+ List<Object> list;
+ if (existingValue == null) {
+ list = new ArrayList<Object>();
+ fields.put(descriptor, list);
+ } else {
+ list = (List<Object>) existingValue;
+ }
+
+ list.add(value);
+ }
+
+ /**
+ * Verifies that the given object is of the correct type to be a valid
+ * value for the given field. (For repeated fields, this checks if the
+ * object is the right type to be one element of the field.)
+ *
+ * @throws IllegalArgumentException The value is not of the right type.
+ */
+ private static void verifyType(final WireFormat.FieldType type,
+ final Object value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+
+ boolean isValid = false;
+ switch (type.getJavaType()) {
+ case INT: isValid = value instanceof Integer ; break;
+ case LONG: isValid = value instanceof Long ; break;
+ case FLOAT: isValid = value instanceof Float ; break;
+ case DOUBLE: isValid = value instanceof Double ; break;
+ case BOOLEAN: isValid = value instanceof Boolean ; break;
+ case STRING: isValid = value instanceof String ; break;
+ case BYTE_STRING:
+ isValid = value instanceof ByteString || value instanceof byte[];
+ break;
+ case ENUM:
+ // TODO(kenton): Caller must do type checking here, I guess.
+ isValid =
+ (value instanceof Integer || value instanceof Internal.EnumLite);
+ break;
+ case MESSAGE:
+ // TODO(kenton): Caller must do type checking here, I guess.
+ isValid =
+ (value instanceof MessageLite) || (value instanceof LazyField);
+ break;
+ }
+
+ if (!isValid) {
+ // TODO(kenton): When chaining calls to setField(), it can be hard to
+ // tell from the stack trace which exact call failed, since the whole
+ // chain is considered one line of code. It would be nice to print
+ // more information here, e.g. naming the field. We used to do that.
+ // But we can't now that FieldSet doesn't use descriptors. Maybe this
+ // isn't a big deal, though, since it would only really apply when using
+ // reflection and generally people don't chain reflection setters.
+ throw new IllegalArgumentException(
+ "Wrong object type used with protocol message reflection.");
+ }
+ }
+
+ // =================================================================
+ // Parsing and serialization
+
+ /**
+ * See {@link Message#isInitialized()}. Note: Since {@code FieldSet}
+ * itself does not have any way of knowing about required fields that
+ * aren't actually present in the set, it is up to the caller to check
+ * that all required fields are present.
+ */
+ public boolean isInitialized() {
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ if (!isInitialized(fields.getArrayEntryAt(i))) {
+ return false;
+ }
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ if (!isInitialized(entry)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ private boolean isInitialized(
+ final Map.Entry<FieldDescriptorType, Object> entry) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+ if (descriptor.isRepeated()) {
+ for (final MessageLite element:
+ (List<MessageLite>) entry.getValue()) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ Object value = entry.getValue();
+ if (value instanceof MessageLite) {
+ if (!((MessageLite) value).isInitialized()) {
+ return false;
+ }
+ } else if (value instanceof LazyField) {
+ return true;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong object type used with protocol message reflection.");
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Given a field type, return the wire type.
+ *
+ * @returns One of the {@code WIRETYPE_} constants defined in
+ * {@link WireFormat}.
+ */
+ static int getWireFormatForFieldType(final WireFormat.FieldType type,
+ boolean isPacked) {
+ if (isPacked) {
+ return WireFormat.WIRETYPE_LENGTH_DELIMITED;
+ } else {
+ return type.getWireType();
+ }
+ }
+
+ /**
+ * Like {@link Message.Builder#mergeFrom(Message)}, but merges from another
+ * {@link FieldSet}.
+ */
+ public void mergeFrom(final FieldSet<FieldDescriptorType> other) {
+ for (int i = 0; i < other.fields.getNumArrayEntries(); i++) {
+ mergeFromField(other.fields.getArrayEntryAt(i));
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ other.fields.getOverflowEntries()) {
+ mergeFromField(entry);
+ }
+ }
+
+ private Object cloneIfMutable(Object value) {
+ if (value instanceof byte[]) {
+ byte[] bytes = (byte[]) value;
+ byte[] copy = new byte[bytes.length];
+ System.arraycopy(bytes, 0, copy, 0, bytes.length);
+ return copy;
+ } else {
+ return value;
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private void mergeFromField(
+ final Map.Entry<FieldDescriptorType, Object> entry) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ Object otherValue = entry.getValue();
+ if (otherValue instanceof LazyField) {
+ otherValue = ((LazyField) otherValue).getValue();
+ }
+
+ if (descriptor.isRepeated()) {
+ Object value = getField(descriptor);
+ if (value == null) {
+ value = new ArrayList();
+ }
+ for (Object element : (List) otherValue) {
+ ((List) value).add(cloneIfMutable(element));
+ }
+ fields.put(descriptor, value);
+ } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {
+ Object value = getField(descriptor);
+ if (value == null) {
+ fields.put(descriptor, cloneIfMutable(otherValue));
+ } else {
+ // Merge the messages.
+ value = descriptor.internalMergeFrom(
+ ((MessageLite) value).toBuilder(), (MessageLite) otherValue)
+ .build();
+
+ fields.put(descriptor, value);
+ }
+ } else {
+ fields.put(descriptor, cloneIfMutable(otherValue));
+ }
+ }
+
+ // TODO(kenton): Move static parsing and serialization methods into some
+ // other class. Probably WireFormat.
+
+ /**
+ * Read a field of any primitive type for immutable messages from a
+ * CodedInputStream. Enums, groups, and embedded messages are not handled by
+ * this method.
+ *
+ * @param input The stream from which to read.
+ * @param type Declared type of the field.
+ * @param checkUtf8 When true, check that the input is valid utf8.
+ * @return An object representing the field's value, of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ public static Object readPrimitiveField(
+ CodedInputStream input,
+ final WireFormat.FieldType type,
+ boolean checkUtf8) throws IOException {
+ if (checkUtf8) {
+ return WireFormat.readPrimitiveField(input, type,
+ WireFormat.Utf8Validation.STRICT);
+ } else {
+ return WireFormat.readPrimitiveField(input, type,
+ WireFormat.Utf8Validation.LOOSE);
+ }
+ }
+
+
+ /** See {@link Message#writeTo(CodedOutputStream)}. */
+ public void writeTo(final CodedOutputStream output)
+ throws IOException {
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ final Map.Entry<FieldDescriptorType, Object> entry =
+ fields.getArrayEntryAt(i);
+ writeField(entry.getKey(), entry.getValue(), output);
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ writeField(entry.getKey(), entry.getValue(), output);
+ }
+ }
+
+ /**
+ * Like {@link #writeTo} but uses MessageSet wire format.
+ */
+ public void writeMessageSetTo(final CodedOutputStream output)
+ throws IOException {
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ writeMessageSetTo(fields.getArrayEntryAt(i), output);
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ writeMessageSetTo(entry, output);
+ }
+ }
+
+ private void writeMessageSetTo(
+ final Map.Entry<FieldDescriptorType, Object> entry,
+ final CodedOutputStream output) throws IOException {
+ final FieldDescriptorType descriptor = entry.getKey();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated() && !descriptor.isPacked()) {
+ Object value = entry.getValue();
+ if (value instanceof LazyField) {
+ value = ((LazyField) value).getValue();
+ }
+ output.writeMessageSetExtension(entry.getKey().getNumber(),
+ (MessageLite) value);
+ } else {
+ writeField(descriptor, entry.getValue(), output);
+ }
+ }
+
+ /**
+ * Write a single tag-value pair to the stream.
+ *
+ * @param output The output stream.
+ * @param type The field's type.
+ * @param number The field's number.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static void writeElement(
+ final CodedOutputStream output,
+ final WireFormat.FieldType type,
+ final int number,
+ final Object value) throws IOException {
+ // Special case for groups, which need a start and end tag; other fields
+ // can just use writeTag() and writeFieldNoTag().
+ if (type == WireFormat.FieldType.GROUP) {
+ output.writeGroup(number, (MessageLite) value);
+ } else {
+ output.writeTag(number, getWireFormatForFieldType(type, false));
+ writeElementNoTag(output, type, value);
+ }
+ }
+
+ /**
+ * Write a field of arbitrary type, without its tag, to the stream.
+ *
+ * @param output The output stream.
+ * @param type The field's type.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static void writeElementNoTag(
+ final CodedOutputStream output,
+ final WireFormat.FieldType type,
+ final Object value) throws IOException {
+ switch (type) {
+ case DOUBLE : output.writeDoubleNoTag ((Double ) value); break;
+ case FLOAT : output.writeFloatNoTag ((Float ) value); break;
+ case INT64 : output.writeInt64NoTag ((Long ) value); break;
+ case UINT64 : output.writeUInt64NoTag ((Long ) value); break;
+ case INT32 : output.writeInt32NoTag ((Integer ) value); break;
+ case FIXED64 : output.writeFixed64NoTag ((Long ) value); break;
+ case FIXED32 : output.writeFixed32NoTag ((Integer ) value); break;
+ case BOOL : output.writeBoolNoTag ((Boolean ) value); break;
+ case GROUP : output.writeGroupNoTag ((MessageLite) value); break;
+ case MESSAGE : output.writeMessageNoTag ((MessageLite) value); break;
+ case STRING:
+ if (value instanceof ByteString) {
+ output.writeBytesNoTag((ByteString) value);
+ } else {
+ output.writeStringNoTag((String) value);
+ }
+ break;
+ case BYTES:
+ if (value instanceof ByteString) {
+ output.writeBytesNoTag((ByteString) value);
+ } else {
+ output.writeByteArrayNoTag((byte[]) value);
+ }
+ break;
+ case UINT32 : output.writeUInt32NoTag ((Integer ) value); break;
+ case SFIXED32: output.writeSFixed32NoTag((Integer ) value); break;
+ case SFIXED64: output.writeSFixed64NoTag((Long ) value); break;
+ case SINT32 : output.writeSInt32NoTag ((Integer ) value); break;
+ case SINT64 : output.writeSInt64NoTag ((Long ) value); break;
+
+ case ENUM:
+ if (value instanceof Internal.EnumLite) {
+ output.writeEnumNoTag(((Internal.EnumLite) value).getNumber());
+ } else {
+ output.writeEnumNoTag(((Integer) value).intValue());
+ }
+ break;
+ }
+ }
+
+ /** Write a single field. */
+ public static void writeField(final FieldDescriptorLite<?> descriptor,
+ final Object value,
+ final CodedOutputStream output)
+ throws IOException {
+ WireFormat.FieldType type = descriptor.getLiteType();
+ int number = descriptor.getNumber();
+ if (descriptor.isRepeated()) {
+ final List<?> valueList = (List<?>)value;
+ if (descriptor.isPacked()) {
+ output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ // Compute the total data size so the length can be written.
+ int dataSize = 0;
+ for (final Object element : valueList) {
+ dataSize += computeElementSizeNoTag(type, element);
+ }
+ output.writeRawVarint32(dataSize);
+ // Write the data itself, without any tags.
+ for (final Object element : valueList) {
+ writeElementNoTag(output, type, element);
+ }
+ } else {
+ for (final Object element : valueList) {
+ writeElement(output, type, number, element);
+ }
+ }
+ } else {
+ if (value instanceof LazyField) {
+ writeElement(output, type, number, ((LazyField) value).getValue());
+ } else {
+ writeElement(output, type, number, value);
+ }
+ }
+ }
+
+ /**
+ * See {@link Message#getSerializedSize()}. It's up to the caller to cache
+ * the resulting size if desired.
+ */
+ public int getSerializedSize() {
+ int size = 0;
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ final Map.Entry<FieldDescriptorType, Object> entry =
+ fields.getArrayEntryAt(i);
+ size += computeFieldSize(entry.getKey(), entry.getValue());
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ size += computeFieldSize(entry.getKey(), entry.getValue());
+ }
+ return size;
+ }
+
+ /**
+ * Like {@link #getSerializedSize} but uses MessageSet wire format.
+ */
+ public int getMessageSetSerializedSize() {
+ int size = 0;
+ for (int i = 0; i < fields.getNumArrayEntries(); i++) {
+ size += getMessageSetSerializedSize(fields.getArrayEntryAt(i));
+ }
+ for (final Map.Entry<FieldDescriptorType, Object> entry :
+ fields.getOverflowEntries()) {
+ size += getMessageSetSerializedSize(entry);
+ }
+ return size;
+ }
+
+ private int getMessageSetSerializedSize(
+ final Map.Entry<FieldDescriptorType, Object> entry) {
+ final FieldDescriptorType descriptor = entry.getKey();
+ Object value = entry.getValue();
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+ && !descriptor.isRepeated() && !descriptor.isPacked()) {
+ if (value instanceof LazyField) {
+ return CodedOutputStream.computeLazyFieldMessageSetExtensionSize(
+ entry.getKey().getNumber(), (LazyField) value);
+ } else {
+ return CodedOutputStream.computeMessageSetExtensionSize(
+ entry.getKey().getNumber(), (MessageLite) value);
+ }
+ } else {
+ return computeFieldSize(descriptor, value);
+ }
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * single tag/value pair of arbitrary type.
+ *
+ * @param type The field's type.
+ * @param number The field's number.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static int computeElementSize(
+ final WireFormat.FieldType type, final int number, final Object value) {
+ int tagSize = CodedOutputStream.computeTagSize(number);
+ if (type == WireFormat.FieldType.GROUP) {
+ // Only count the end group tag for proto2 messages as for proto1 the end
+ // group tag will be counted as a part of getSerializedSize().
+ tagSize *= 2;
+ }
+ return tagSize + computeElementSizeNoTag(type, value);
+ }
+
+ /**
+ * Compute the number of bytes that would be needed to encode a
+ * particular value of arbitrary type, excluding tag.
+ *
+ * @param type The field's type.
+ * @param value Object representing the field's value. Must be of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static int computeElementSizeNoTag(
+ final WireFormat.FieldType type, final Object value) {
+ switch (type) {
+ // Note: Minor violation of 80-char limit rule here because this would
+ // actually be harder to read if we wrapped the lines.
+ case DOUBLE : return CodedOutputStream.computeDoubleSizeNoTag ((Double )value);
+ case FLOAT : return CodedOutputStream.computeFloatSizeNoTag ((Float )value);
+ case INT64 : return CodedOutputStream.computeInt64SizeNoTag ((Long )value);
+ case UINT64 : return CodedOutputStream.computeUInt64SizeNoTag ((Long )value);
+ case INT32 : return CodedOutputStream.computeInt32SizeNoTag ((Integer )value);
+ case FIXED64 : return CodedOutputStream.computeFixed64SizeNoTag ((Long )value);
+ case FIXED32 : return CodedOutputStream.computeFixed32SizeNoTag ((Integer )value);
+ case BOOL : return CodedOutputStream.computeBoolSizeNoTag ((Boolean )value);
+ case GROUP : return CodedOutputStream.computeGroupSizeNoTag ((MessageLite)value);
+ case BYTES :
+ if (value instanceof ByteString) {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ return CodedOutputStream.computeByteArraySizeNoTag((byte[]) value);
+ }
+ case STRING :
+ if (value instanceof ByteString) {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ }
+ case UINT32 : return CodedOutputStream.computeUInt32SizeNoTag ((Integer )value);
+ case SFIXED32: return CodedOutputStream.computeSFixed32SizeNoTag((Integer )value);
+ case SFIXED64: return CodedOutputStream.computeSFixed64SizeNoTag((Long )value);
+ case SINT32 : return CodedOutputStream.computeSInt32SizeNoTag ((Integer )value);
+ case SINT64 : return CodedOutputStream.computeSInt64SizeNoTag ((Long )value);
+
+ case MESSAGE:
+ if (value instanceof LazyField) {
+ return CodedOutputStream.computeLazyFieldSizeNoTag((LazyField) value);
+ } else {
+ return CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
+ }
+
+ case ENUM:
+ if (value instanceof Internal.EnumLite) {
+ return CodedOutputStream.computeEnumSizeNoTag(
+ ((Internal.EnumLite) value).getNumber());
+ } else {
+ return CodedOutputStream.computeEnumSizeNoTag((Integer) value);
+ }
+ }
+
+ throw new RuntimeException(
+ "There is no way to get here, but the compiler thinks otherwise.");
+ }
+
+ /**
+ * Compute the number of bytes needed to encode a particular field.
+ */
+ public static int computeFieldSize(final FieldDescriptorLite<?> descriptor,
+ final Object value) {
+ WireFormat.FieldType type = descriptor.getLiteType();
+ int number = descriptor.getNumber();
+ if (descriptor.isRepeated()) {
+ if (descriptor.isPacked()) {
+ int dataSize = 0;
+ for (final Object element : (List<?>)value) {
+ dataSize += computeElementSizeNoTag(type, element);
+ }
+ return dataSize +
+ CodedOutputStream.computeTagSize(number) +
+ CodedOutputStream.computeRawVarint32Size(dataSize);
+ } else {
+ int size = 0;
+ for (final Object element : (List<?>)value) {
+ size += computeElementSize(type, number, element);
+ }
+ return size;
+ }
+ } else {
+ return computeElementSize(type, number, value);
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
new file mode 100644
index 0000000000..90d6154b15
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -0,0 +1,272 @@
+// 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 com.google.protobuf.Internal.FloatList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link FloatList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class FloatArrayList
+ extends AbstractProtobufList<Float>
+ implements FloatList, RandomAccess {
+
+ private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static FloatArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private float[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code FloatArrayList} with default capacity.
+ */
+ FloatArrayList() {
+ this(new float[DEFAULT_CAPACITY], 0);
+ }
+
+ /**
+ * Constructs a new mutable {@code FloatArrayList}
+ * containing the same elements as {@code other}.
+ */
+ private FloatArrayList(float[] other, int size) {
+ array = other;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof FloatArrayList)) {
+ return super.equals(o);
+ }
+ FloatArrayList other = (FloatArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final float[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Float.floatToIntBits(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public FloatList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new FloatArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
+ @Override
+ public Float get(int index) {
+ return getFloat(index);
+ }
+
+ @Override
+ public float getFloat(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Float set(int index, Float element) {
+ return setFloat(index, element);
+ }
+
+ @Override
+ public float setFloat(int index, float element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ float previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Float element) {
+ addFloat(index, element);
+ }
+
+ /**
+ * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addFloat(float element) {
+ addFloat(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Float)} but more efficient in that it doesn't box the element.
+ */
+ private void addFloat(int index, float element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ float[] newArray = new float[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Float> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another FloatArrayList to avoid boxing elements.
+ if (!(collection instanceof FloatArrayList)) {
+ return super.addAll(collection);
+ }
+
+ FloatArrayList list = (FloatArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Float remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ float value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
new file mode 100644
index 0000000000..60179e371d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -0,0 +1,3051 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+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 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.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * All generated protocol message classes extend this class. This class
+ * implements most of the Message and Builder interfaces using Java reflection.
+ * Users can ignore this class and pretend that generated messages implement
+ * the Message interface directly.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessage extends AbstractMessage
+ implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ */
+ protected static boolean alwaysUseFieldBuilders = false;
+
+ /** For use by generated code only. */
+ protected UnknownFieldSet unknownFields;
+
+ protected GeneratedMessage() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ }
+
+ protected GeneratedMessage(Builder<?> builder) {
+ unknownFields = builder.getUnknownFields();
+ }
+
+ @Override
+ public Parser<? extends GeneratedMessage> getParserForType() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+ */
+ static void enableAlwaysUseFieldBuildersForTesting() {
+ alwaysUseFieldBuilders = true;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ /**
+ * Internal helper to return a modifiable map containing all the fields.
+ * The returned Map is modifialbe so that the caller can add additional
+ * extension fields to implement {@link #getAllFields()}.
+ *
+ * @param getBytesForString whether to generate ByteString for string fields
+ */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable(
+ boolean getBytesForString) {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
+ }
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
+ } else {
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
+ }
+ }
+ // Add the field to the map
+ if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ result.put(field, getFieldRaw(field));
+ } else {
+ result.put(field, getField(field));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) && !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ false));
+ }
+
+ /**
+ * Returns a collection of all the fields in this message which are set
+ * and their corresponding values. A singular ("required" or "optional")
+ * field is set iff hasField() returns true for that field. A "repeated"
+ * field is set iff getRepeatedFieldCount() is greater than zero. The
+ * values are exactly what would be returned by calling
+ * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map
+ * is guaranteed to be a sorted map, so iterating over it will return fields
+ * in order by field number.
+ */
+ Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ true));
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).get(this);
+ }
+
+ /**
+ * Obtains the value of the given field, or the default value if it is
+ * not set. For primitive fields, the boxed primitive value is returned.
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned. For present string fields, a
+ * ByteString is returned representing the bytes that the field contains.
+ */
+ Object getFieldRaw(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getRaw(this);
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ 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);
+ }
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(
+ this, getAllFieldsRaw());
+ return memoizedSize;
+ }
+
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ protected void makeExtensionsImmutable() {
+ // Noop for messages without extensions.
+ }
+
+ /**
+ * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
+ * interface to AbstractMessage in order to versioning GeneratedMessage but
+ * this move breaks binary compatibility for AppEngine. After AppEngine is
+ * fixed we can exlude this from google3.
+ */
+ protected interface BuilderParent extends AbstractMessage.BuilderParent {}
+
+ /**
+ * TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent.
+ */
+ protected abstract Message.Builder newBuilderForType(BuilderParent parent);
+
+ @Override
+ protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
+ return newBuilderForType(new BuilderParent() {
+ @Override
+ public void markDirty() {
+ parent.markDirty();
+ }
+ });
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder <BuilderType extends Builder<BuilderType>>
+ extends AbstractMessage.Builder<BuilderType> {
+
+ private BuilderParent builderParent;
+
+ private BuilderParentImpl meAsParent;
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+ private boolean isClean;
+
+ private UnknownFieldSet unknownFields =
+ UnknownFieldSet.getDefaultInstance();
+
+ protected Builder() {
+ this(null);
+ }
+
+ protected Builder(BuilderParent builderParent) {
+ this.builderParent = builderParent;
+ }
+
+ @Override
+ void dispose() {
+ builderParent = null;
+ }
+
+ /**
+ * Called by the subclass when a message is built.
+ */
+ protected void onBuilt() {
+ if (builderParent != null) {
+ markClean();
+ }
+ }
+
+ /**
+ * Called by the subclass or a builder to notify us that a message was
+ * built and may be cached and therefore invalidations are needed.
+ */
+ @Override
+ protected void markClean() {
+ this.isClean = true;
+ }
+
+ /**
+ * Gets whether invalidations are needed
+ *
+ * @return whether invalidations are needed
+ */
+ protected boolean isClean() {
+ return isClean;
+ }
+
+ @Override
+ public BuilderType clone() {
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
+ }
+
+ /**
+ * Called by the initialization and clear code paths to allow subclasses to
+ * reset any of their builtin fields back to the initial values.
+ */
+ @Override
+ public BuilderType clear() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(getAllFieldsMutable());
+ }
+
+ /** Internal helper which returns a mutable map. */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
+ }
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
+ } else {
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
+ }
+ }
+ // Add the field to the map
+ result.put(field, getField(field));
+ }
+ return result;
+ }
+
+ @Override
+ public Message.Builder newBuilderForField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).newBuilder();
+ }
+
+ @Override
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+ }
+
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+ return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
+ this, index);
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ Object object = internalGetFieldAccessorTable().getField(field).get(this);
+ if (field.isRepeated()) {
+ // The underlying list object is still modifiable at this point.
+ // Make sure not to expose the modifiable list to the caller.
+ return Collections.unmodifiableList((List) object);
+ } else {
+ return object;
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).set(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ internalGetFieldAccessorTable().getField(field).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearOneof(final OneofDescriptor oneof) {
+ internalGetFieldAccessorTable().getOneof(oneof).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public BuilderType setRepeatedField(
+ final FieldDescriptor field, final int index, final Object value) {
+ internalGetFieldAccessorTable().getField(field)
+ .setRepeated(this, index, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
+ this.unknownFields = unknownFields;
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeUnknownFields(
+ final UnknownFieldSet unknownFields) {
+ this.unknownFields =
+ UnknownFieldSet.newBuilder(this.unknownFields)
+ .mergeFrom(unknownFields)
+ .build();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) &&
+ !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final UnknownFieldSet getUnknownFields() {
+ return unknownFields;
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ /**
+ * Implementation of {@link BuilderParent} for giving to our children. This
+ * small inner class makes it so we don't publicly expose the BuilderParent
+ * methods.
+ */
+ private class BuilderParentImpl implements BuilderParent {
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+ }
+
+ /**
+ * Gets the {@link BuilderParent} for giving to our children.
+ * @return The builder parent for our children.
+ */
+ protected BuilderParent getParentForChildren() {
+ if (meAsParent == null) {
+ meAsParent = new BuilderParentImpl();
+ }
+ return meAsParent;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ protected final void onChanged() {
+ if (isClean && builderParent != null) {
+ builderParent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /** 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
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+ }
+
+ // =================================================================
+ // Extensions-related stuff
+
+ public interface ExtendableMessageOrBuilder<
+ MessageType extends ExtendableMessage> extends MessageOrBuilder {
+ // Re-define for return type covariance.
+ @Override
+ Message getDefaultInstanceForType();
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ ExtensionLite<MessageType, List<Type>> extension);
+
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, List<Type>> extension,
+ int index);
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ Extension<MessageType, Type> extension);
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ Extension<MessageType, List<Type>> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ GeneratedExtension<MessageType, List<Type>> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, Type> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, List<Type>> extension,
+ int index);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, List<Type>> extension,
+ int index);
+ }
+
+ /**
+ * Generated message classes for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "has", "get", and "getCount" -- but for extensions. The extensions
+ * are identified using instances of the class {@link GeneratedExtension};
+ * the protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo = getFoo();
+ * int i = foo.getExtension(MyProto.bar);
+ * </pre>
+ *
+ * <p>See also {@link ExtendableBuilder}.
+ */
+ public abstract static class ExtendableMessage<
+ MessageType extends ExtendableMessage>
+ extends GeneratedMessage
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final FieldSet<FieldDescriptor> extensions;
+
+ protected ExtendableMessage() {
+ this.extensions = FieldSet.newFieldSet();
+ }
+
+ protected ExtendableMessage(
+ ExtendableBuilder<MessageType, ?> builder) {
+ super(builder);
+ this.extensions = builder.buildExtensions();
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ @Override
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.ExtensionAdapter(extensions), tag);
+ }
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ @Override
+ protected void makeExtensionsImmutable() {
+ extensions.makeImmutable();
+ }
+
+ /**
+ * Used by subclasses to serialize extensions. Extension ranges may be
+ * interleaved with field numbers, but we must write them in canonical
+ * (sorted by field number) order. ExtensionWriter helps us write
+ * individual ranges of extensions at once.
+ */
+ protected class ExtensionWriter {
+ // Imagine how much simpler this code would be if Java iterators had
+ // a way to get the next element without advancing the iterator.
+
+ private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+ extensions.iterator();
+ private Map.Entry<FieldDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
+
+ private ExtensionWriter(final boolean messageSetWireFormat) {
+ if (iter.hasNext()) {
+ next = iter.next();
+ }
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void writeUntil(final int end, final CodedOutputStream output)
+ throws IOException {
+ while (next != null && next.getKey().getNumber() < end) {
+ FieldDescriptor descriptor = next.getKey();
+ if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated()) {
+ if (next instanceof LazyField.LazyEntry<?>) {
+ output.writeRawMessageSetExtension(descriptor.getNumber(),
+ ((LazyField.LazyEntry<?>) next).getField().toByteString());
+ } else {
+ output.writeMessageSetExtension(descriptor.getNumber(),
+ (Message) next.getValue());
+ }
+ } else {
+ // TODO(xiangl): Taken care of following code, it may cause
+ // problem when we use LazyField for normal fields/extensions.
+ // Due to the optional field can be duplicated at the end of
+ // serialized bytes, which will make the serialized size change
+ // after lazy field parsed. So when we use LazyField globally,
+ // we need to change the following write method to write cached
+ // bytes directly rather than write the parsed message.
+ FieldSet.writeField(descriptor, next.getValue(), output);
+ }
+ if (iter.hasNext()) {
+ next = iter.next();
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter newExtensionWriter() {
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
+ }
+
+ /** Called by subclasses to compute the size of extensions. */
+ protected int extensionsSerializedSize() {
+ return extensions.getSerializedSize();
+ }
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ protected Map<FieldDescriptor, Object> getExtensionFields() {
+ return extensions.getAllFields();
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.isRepeated()) {
+ return Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ /**
+ * Generated message builders for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "get", "set", and "add" -- but for extensions. The extensions are
+ * identified using instances of the class {@link GeneratedExtension}; the
+ * protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo =
+ * MyProto.Foo.newBuilder()
+ * .setExtension(MyProto.bar, 123)
+ * .build();
+ * </pre>
+ *
+ * <p>See also {@link ExtendableMessage}.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class ExtendableBuilder<
+ MessageType extends ExtendableMessage,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends Builder<BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
+
+ protected ExtendableBuilder() {}
+
+ protected ExtendableBuilder(
+ BuilderParent parent) {
+ super(parent);
+ }
+
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
+ @Override
+ public BuilderType clear() {
+ extensions = FieldSet.emptySet();
+ return super.clear();
+ }
+
+ // This is implemented here only to work around an apparent bug in the
+ // Java compiler and/or build system. See bug #1898463. The mere presence
+ // of this clone() implementation makes it go away.
+ @Override
+ public BuilderType clone() {
+ return super.clone();
+ }
+
+ private void ensureExtensionsIsMutable() {
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
+ }
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, Type> extensionLite,
+ final Type value) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setField(descriptor, extension.toReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final int index, final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setRepeatedField(
+ descriptor, index,
+ extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.addRepeatedField(
+ descriptor, extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final ExtensionLite<MessageType, ?> extensionLite) {
+ Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ extensions.clearField(extension.getDescriptor());
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of an extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final Extension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Append a value to a repeated extension. */
+ public <Type> BuilderType addExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final Extension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+ /** Clear an extension. */
+ public <Type> BuilderType clearExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ /**
+ * Called by the build code path to create a copy of the extensions for
+ * building the message.
+ */
+ private FieldSet<FieldDescriptor> buildExtensions() {
+ extensions.makeImmutable();
+ return extensions;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @Override
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.BuilderAdapter(this), tag);
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+ result.putAll(extensions.getAllFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setField(field, value);
+ }
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.clearField(field);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.clearField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setRepeatedField(final FieldDescriptor field,
+ final int index, final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setRepeatedField(field, index, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setRepeatedField(field, index, value);
+ }
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.addRepeatedField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.addRepeatedField(field, value);
+ }
+ }
+
+ protected final void mergeExtensionFields(final ExtendableMessage other) {
+ ensureExtensionsIsMutable();
+ extensions.mergeFrom(other.extensions);
+ onChanged();
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Gets the descriptor for an extension. The implementation depends on whether
+ * the extension is scoped in the top level of a file or scoped in a Message.
+ */
+ static interface ExtensionDescriptorRetriever {
+ FieldDescriptor getDescriptor();
+ }
+
+ /** For use by generated code only. */
+ public static <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ newMessageScopedGeneratedExtension(final Message scope,
+ final int descriptorIndex,
+ final Class singularType,
+ final Message defaultInstance) {
+ // For extensions scoped within a Message, we use the Message to resolve
+ // the outer class's descriptor, from which the extension descriptor is
+ // obtained.
+ return new GeneratedExtension<ContainingType, Type>(
+ new CachedDescriptorRetriever() {
+ @Override
+ public FieldDescriptor loadDescriptor() {
+ return scope.getDescriptorForType().getExtensions().get(descriptorIndex);
+ }
+ },
+ singularType,
+ defaultInstance,
+ Extension.ExtensionType.IMMUTABLE);
+ }
+
+ /** For use by generated code only. */
+ public static <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ newFileScopedGeneratedExtension(final Class singularType,
+ final Message defaultInstance) {
+ // For extensions scoped within a file, we rely on the outer class's
+ // static initializer to call internalInit() on the extension when the
+ // descriptor is available.
+ return new GeneratedExtension<ContainingType, Type>(
+ null, // ExtensionDescriptorRetriever is initialized in internalInit();
+ singularType,
+ defaultInstance,
+ Extension.ExtensionType.IMMUTABLE);
+ }
+
+ private abstract static class CachedDescriptorRetriever
+ implements ExtensionDescriptorRetriever {
+ private volatile FieldDescriptor descriptor;
+ protected abstract FieldDescriptor loadDescriptor();
+
+ @Override
+ public FieldDescriptor getDescriptor() {
+ if (descriptor == null) {
+ synchronized (this) {
+ if (descriptor == null) {
+ descriptor = loadDescriptor();
+ }
+ }
+ }
+ return descriptor;
+ }
+ }
+
+ /**
+ * Used in proto1 generated code only.
+ *
+ * After enabling bridge, we can define proto2 extensions (the extended type
+ * is a proto2 mutable message) in a proto1 .proto file. For these extensions
+ * we should generate proto2 GeneratedExtensions.
+ */
+ public static <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ newMessageScopedGeneratedExtension(
+ final Message scope, final String name,
+ final Class singularType, final Message defaultInstance) {
+ // For extensions scoped within a Message, we use the Message to resolve
+ // the outer class's descriptor, from which the extension descriptor is
+ // obtained.
+ return new GeneratedExtension<ContainingType, Type>(
+ new CachedDescriptorRetriever() {
+ @Override
+ protected FieldDescriptor loadDescriptor() {
+ return scope.getDescriptorForType().findFieldByName(name);
+ }
+ },
+ singularType,
+ defaultInstance,
+ Extension.ExtensionType.MUTABLE);
+ }
+
+ /**
+ * Used in proto1 generated code only.
+ *
+ * After enabling bridge, we can define proto2 extensions (the extended type
+ * is a proto2 mutable message) in a proto1 .proto file. For these extensions
+ * we should generate proto2 GeneratedExtensions.
+ */
+ public static <ContainingType extends Message, Type>
+ GeneratedExtension<ContainingType, Type>
+ newFileScopedGeneratedExtension(
+ final Class singularType, final Message defaultInstance,
+ final String descriptorOuterClass, final String extensionName) {
+ // For extensions scoped within a file, we load the descriptor outer
+ // class and rely on it to get the FileDescriptor which then can be
+ // used to obtain the extension's FieldDescriptor.
+ return new GeneratedExtension<ContainingType, Type>(
+ new CachedDescriptorRetriever() {
+ @Override
+ protected FieldDescriptor loadDescriptor() {
+ try {
+ Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass);
+ FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null);
+ return file.findExtensionByName(extensionName);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Cannot load descriptors: "
+ + descriptorOuterClass
+ + " is not a valid descriptor class name",
+ e);
+ }
+ }
+ },
+ singularType,
+ defaultInstance,
+ Extension.ExtensionType.MUTABLE);
+ }
+
+ /**
+ * Type used to represent generated extensions. The protocol compiler
+ * generates a static singleton instance of this class for each extension.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then, {@code MyProto.Foo.bar} has type
+ * {@code GeneratedExtension<MyProto.Foo, Integer>}.
+ *
+ * <p>In general, users should ignore the details of this type, and simply use
+ * these static singletons as parameters to the extension accessors defined
+ * in {@link ExtendableMessage} and {@link ExtendableBuilder}.
+ */
+ public static class GeneratedExtension<
+ ContainingType extends Message, Type> extends
+ Extension<ContainingType, Type> {
+ // TODO(kenton): Find ways to avoid using Java reflection within this
+ // class. Also try to avoid suppressing unchecked warnings.
+
+ // We can't always initialize the descriptor of a GeneratedExtension when
+ // we first construct it due to initialization order difficulties (namely,
+ // the descriptor may not have been constructed yet, since it is often
+ // constructed by the initializer of a separate module).
+ //
+ // In the case of nested extensions, we initialize the
+ // ExtensionDescriptorRetriever with an instance that uses the scoping
+ // Message's default instance to retrieve the extension's descriptor.
+ //
+ // In the case of non-nested extensions, we initialize the
+ // ExtensionDescriptorRetriever to null and rely on the outer class's static
+ // initializer to call internalInit() after the descriptor has been parsed.
+ GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
+ Class singularType,
+ Message messageDefaultInstance,
+ ExtensionType extensionType) {
+ if (Message.class.isAssignableFrom(singularType) &&
+ !singularType.isInstance(messageDefaultInstance)) {
+ throw new IllegalArgumentException(
+ "Bad messageDefaultInstance for " + singularType.getName());
+ }
+ this.descriptorRetriever = descriptorRetriever;
+ this.singularType = singularType;
+ this.messageDefaultInstance = messageDefaultInstance;
+
+ if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
+ this.enumValueOf = getMethodOrDie(singularType, "valueOf",
+ EnumValueDescriptor.class);
+ this.enumGetValueDescriptor =
+ getMethodOrDie(singularType, "getValueDescriptor");
+ } else {
+ this.enumValueOf = null;
+ this.enumGetValueDescriptor = null;
+ }
+ this.extensionType = extensionType;
+ }
+
+ /** For use by generated code only. */
+ public void internalInit(final FieldDescriptor descriptor) {
+ if (descriptorRetriever != null) {
+ throw new IllegalStateException("Already initialized.");
+ }
+ descriptorRetriever =
+ new ExtensionDescriptorRetriever() {
+ @Override
+ public FieldDescriptor getDescriptor() {
+ return descriptor;
+ }
+ };
+ }
+
+ private ExtensionDescriptorRetriever descriptorRetriever;
+ private final Class singularType;
+ private final Message messageDefaultInstance;
+ private final Method enumValueOf;
+ private final Method enumGetValueDescriptor;
+ private final ExtensionType extensionType;
+
+ @Override
+ public FieldDescriptor getDescriptor() {
+ if (descriptorRetriever == null) {
+ throw new IllegalStateException(
+ "getDescriptor() called before internalInit()");
+ }
+ return descriptorRetriever.getDescriptor();
+ }
+
+ /**
+ * If the extension is an embedded message or group, returns the default
+ * instance of the message.
+ */
+ @Override
+ public Message getMessageDefaultInstance() {
+ return messageDefaultInstance;
+ }
+
+ @Override
+ protected ExtensionType getExtensionType() {
+ return extensionType;
+ }
+
+ /**
+ * Convert from the type used by the reflection accessors to the type used
+ * by native accessors. E.g., for enums, the reflection accessors use
+ * EnumValueDescriptors but the native accessors use the generated enum
+ * type.
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Object fromReflectionType(final Object value) {
+ FieldDescriptor descriptor = getDescriptor();
+ if (descriptor.isRepeated()) {
+ if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
+ descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ // Must convert the whole list.
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
+ result.add(singularFromReflectionType(element));
+ }
+ return result;
+ } else {
+ return value;
+ }
+ } else {
+ return singularFromReflectionType(value);
+ }
+ }
+
+ /**
+ * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
+ * type, this converts a single element.
+ */
+ @Override
+ protected Object singularFromReflectionType(final Object value) {
+ FieldDescriptor descriptor = getDescriptor();
+ switch (descriptor.getJavaType()) {
+ case MESSAGE:
+ if (singularType.isInstance(value)) {
+ return value;
+ } else {
+ return messageDefaultInstance.newBuilderForType()
+ .mergeFrom((Message) value).build();
+ }
+ case ENUM:
+ return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
+ default:
+ return value;
+ }
+ }
+
+ /**
+ * Convert from the type used by the native accessors to the type used
+ * by reflection accessors. E.g., for enums, the reflection accessors use
+ * EnumValueDescriptors but the native accessors use the generated enum
+ * type.
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Object toReflectionType(final Object value) {
+ FieldDescriptor descriptor = getDescriptor();
+ if (descriptor.isRepeated()) {
+ if (descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ // Must convert the whole list.
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
+ result.add(singularToReflectionType(element));
+ }
+ return result;
+ } else {
+ return value;
+ }
+ } else {
+ return singularToReflectionType(value);
+ }
+ }
+
+ /**
+ * Like {@link #toReflectionType(Object)}, but if the type is a repeated
+ * type, this converts a single element.
+ */
+ @Override
+ protected Object singularToReflectionType(final Object value) {
+ FieldDescriptor descriptor = getDescriptor();
+ switch (descriptor.getJavaType()) {
+ case ENUM:
+ return invokeOrDie(enumGetValueDescriptor, value);
+ default:
+ return value;
+ }
+ }
+
+ @Override
+ public int getNumber() {
+ return getDescriptor().getNumber();
+ }
+
+ @Override
+ public WireFormat.FieldType getLiteType() {
+ return getDescriptor().getLiteType();
+ }
+
+ @Override
+ public boolean isRepeated() {
+ return getDescriptor().isRepeated();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Type getDefaultValue() {
+ if (isRepeated()) {
+ return (Type) Collections.emptyList();
+ }
+ if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) messageDefaultInstance;
+ }
+ return (Type) singularFromReflectionType(
+ getDescriptor().getDefaultValue());
+ }
+ }
+
+ // =================================================================
+
+ /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+ @SuppressWarnings("unchecked")
+ private static Method getMethodOrDie(
+ final Class clazz, final String name, final Class... params) {
+ try {
+ return clazz.getMethod(name, params);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(
+ "Generated message class \"" + clazz.getName() +
+ "\" missing method \"" + name + "\".", e);
+ }
+ }
+
+ /** Calls invoke and throws a RuntimeException if it fails. */
+ private static Object invokeOrDie(
+ final Method method, final Object object, final Object... params) {
+ try {
+ return method.invoke(object, params);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Couldn't use Java reflection to implement protocol message " +
+ "reflection.", e);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(
+ "Unexpected exception thrown by generated accessor method.", cause);
+ }
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"rawtypes", "unused"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /**
+ * Users should ignore this class. This class provides the implementation
+ * with access to the fields of a message object using Java reflection.
+ */
+ public static final class FieldAccessorTable {
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class. Only
+ * one FieldAccessorTable should ever be constructed per class.
+ *
+ * @param descriptor The type's descriptor.
+ * @param camelCaseNames The camelcase names of all fields in the message.
+ * These are used to derive the accessor method names.
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this(descriptor, camelCaseNames);
+ ensureFieldAccessorsInitialized(messageClass, builderClass);
+ }
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class without
+ * initializing FieldAccessors.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames) {
+ this.descriptor = descriptor;
+ this.camelCaseNames = camelCaseNames;
+ fields = new FieldAccessor[descriptor.getFields().size()];
+ oneofs = new OneofAccessor[descriptor.getOneofs().size()];
+ initialized = false;
+ }
+
+ private boolean isMapFieldEnabled(FieldDescriptor field) {
+ boolean result = true;
+ return result;
+ }
+
+ /**
+ * Ensures the field accessors are initialized. This method is thread-safe.
+ *
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ * @return this
+ */
+ public FieldAccessorTable ensureFieldAccessorsInitialized(
+ Class<? extends GeneratedMessage> messageClass,
+ Class<? extends Builder> builderClass) {
+ if (initialized) { return this; }
+ synchronized (this) {
+ if (initialized) { return this; }
+ int fieldsSize = fields.length;
+ for (int i = 0; i < fieldsSize; i++) {
+ FieldDescriptor field = descriptor.getFields().get(i);
+ String containingOneofCamelCaseName = null;
+ if (field.getContainingOneof() != null) {
+ containingOneofCamelCaseName =
+ camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
+ }
+ if (field.isRepeated()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isMapField() && isMapFieldEnabled(field)) {
+ fields[i] = new MapFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new RepeatedEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ fields[i] = new SingularMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new SingularEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ fields[i] = new SingularStringFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else {
+ fields[i] = new SingularFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ }
+ }
+ }
+
+ int oneofsSize = oneofs.length;
+ for (int i = 0; i < oneofsSize; i++) {
+ oneofs[i] = new OneofAccessor(
+ descriptor, camelCaseNames[i + fieldsSize],
+ messageClass, builderClass);
+ }
+ initialized = true;
+ camelCaseNames = null;
+ return this;
+ }
+ }
+
+ private final Descriptor descriptor;
+ private final FieldAccessor[] fields;
+ private String[] camelCaseNames;
+ private final OneofAccessor[] oneofs;
+ private volatile boolean initialized;
+
+ /** Get the FieldAccessor for a particular field. */
+ private FieldAccessor getField(final FieldDescriptor field) {
+ if (field.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ } else if (field.isExtension()) {
+ // If this type had extensions, it would subclass ExtendableMessage,
+ // which overrides the reflection interface to handle extensions.
+ throw new IllegalArgumentException(
+ "This type does not have extensions.");
+ }
+ return fields[field.getIndex()];
+ }
+
+ /** Get the OneofAccessor for a particular oneof. */
+ private OneofAccessor getOneof(final OneofDescriptor oneof) {
+ if (oneof.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "OneofDescriptor does not match message type.");
+ }
+ return oneofs[oneof.getIndex()];
+ }
+
+ /**
+ * Abstract interface that provides access to a single field. This is
+ * implemented differently depending on the field type and cardinality.
+ */
+ private interface FieldAccessor {
+ Object get(GeneratedMessage message);
+ Object get(GeneratedMessage.Builder builder);
+ Object getRaw(GeneratedMessage message);
+ Object getRaw(GeneratedMessage.Builder builder);
+ void set(Builder builder, Object value);
+ Object getRepeated(GeneratedMessage message, int index);
+ Object getRepeated(GeneratedMessage.Builder builder, int index);
+ Object getRepeatedRaw(GeneratedMessage message, int index);
+ Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
+ void setRepeated(Builder builder,
+ int index, Object value);
+ void addRepeated(Builder builder, Object value);
+ boolean has(GeneratedMessage message);
+ boolean has(GeneratedMessage.Builder builder);
+ int getRepeatedCount(GeneratedMessage message);
+ int getRepeatedCount(GeneratedMessage.Builder builder);
+ void clear(Builder builder);
+ Message.Builder newBuilder();
+ Message.Builder getBuilder(GeneratedMessage.Builder builder);
+ Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
+ int index);
+ }
+
+ /** OneofAccessor provides access to a single oneof. */
+ private static class OneofAccessor {
+ OneofAccessor(
+ final Descriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this.descriptor = descriptor;
+ caseMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
+ caseMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ private final Descriptor descriptor;
+ private final Method caseMethod;
+ private final Method caseMethodBuilder;
+ private final Method clearMethod;
+
+ public boolean has(final GeneratedMessage message) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean has(GeneratedMessage.Builder builder) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public FieldDescriptor get(final GeneratedMessage message) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public FieldDescriptor get(GeneratedMessage.Builder builder) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ }
+
+ private static boolean supportFieldPresence(FileDescriptor file) {
+ return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
+ }
+
+ // ---------------------------------------------------------------
+
+ private static class SingularFieldAccessor implements FieldAccessor {
+ SingularFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ field = descriptor;
+ isOneofField = descriptor.getContainingOneof() != null;
+ hasHasMethod = supportFieldPresence(descriptor.getFile())
+ || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
+ type = getMethod.getReturnType();
+ setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
+ hasMethod =
+ hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+ hasMethodBuilder =
+ hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ caseMethod = isOneofField ? getMethodOrDie(
+ messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ caseMethodBuilder = isOneofField ? getMethodOrDie(
+ builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ }
+
+ // Note: We use Java reflection to call public methods rather than
+ // access private fields directly as this avoids runtime security
+ // checks.
+ protected final Class<?> type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method setMethod;
+ protected final Method hasMethod;
+ protected final Method hasMethodBuilder;
+ protected final Method clearMethod;
+ protected final Method caseMethod;
+ protected final Method caseMethodBuilder;
+ protected final FieldDescriptor field;
+ protected final boolean isOneofField;
+ protected final boolean hasHasMethod;
+
+ private int getOneofFieldNumber(final GeneratedMessage message) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ }
+
+ private int getOneofFieldNumber(final GeneratedMessage.Builder builder) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ }
+
+ @Override
+ public Object get(final GeneratedMessage message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessage.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessage message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ invokeOrDie(setMethod, builder, value);
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessage message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ throw new UnsupportedOperationException(
+ "setRepeatedField() called on a singular field.");
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ throw new UnsupportedOperationException(
+ "addRepeatedField() called on a singular field.");
+ }
+ @Override
+ public boolean has(final GeneratedMessage message) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(message) == field.getNumber();
+ }
+ return !get(message).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethod, message);
+ }
+ @Override
+ public boolean has(GeneratedMessage.Builder builder) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(builder) == field.getNumber();
+ }
+ return !get(builder).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessage message) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class RepeatedFieldAccessor implements FieldAccessor {
+ protected final Class type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method getRepeatedMethod;
+ protected final Method getRepeatedMethodBuilder;
+ protected final Method setRepeatedMethod;
+ protected final Method addRepeatedMethod;
+ protected final Method getCountMethod;
+ protected final Method getCountMethodBuilder;
+ protected final Method clearMethod;
+
+ RepeatedFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ getMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "List");
+ getMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "List");
+ getRepeatedMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+ getRepeatedMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
+ type = getRepeatedMethod.getReturnType();
+ setRepeatedMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName,
+ Integer.TYPE, type);
+ addRepeatedMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName, type);
+ getCountMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+ getCountMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ @Override
+ public Object get(final GeneratedMessage message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessage.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessage message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ // Add all the elements individually. This serves two purposes:
+ // 1) Verifies that each element has the correct type.
+ // 2) Insures that the caller cannot modify the list later on and
+ // have the modifications be reflected in the message.
+ clear(builder);
+ for (final Object element : (List<?>) value) {
+ addRepeated(builder, element);
+ }
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessage message, final int index) {
+ return invokeOrDie(getRepeatedMethod, message, index);
+ }
+ @Override
+ public Object getRepeated(GeneratedMessage.Builder builder, int index) {
+ return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage message, int index) {
+ return getRepeated(message, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ invokeOrDie(setRepeatedMethod, builder, index, value);
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ invokeOrDie(addRepeatedMethod, builder, value);
+ }
+ @Override
+ public boolean has(final GeneratedMessage message) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public boolean has(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessage message) {
+ return (Integer) invokeOrDie(getCountMethod, message);
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessage.Builder builder) {
+ return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class MapFieldAccessor implements FieldAccessor {
+ MapFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ field = descriptor;
+ Method getDefaultInstanceMethod =
+ getMethodOrDie(messageClass, "getDefaultInstance");
+ MapField defaultMapField = getMapField(
+ (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
+ mapEntryMessageDefaultInstance =
+ defaultMapField.getMapEntryMessageDefaultInstance();
+ }
+
+ private final FieldDescriptor field;
+ private final Message mapEntryMessageDefaultInstance;
+
+ private MapField<?, ?> getMapField(GeneratedMessage message) {
+ return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMapField(GeneratedMessage.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMutableMapField(
+ GeneratedMessage.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMutableMapField(
+ field.getNumber());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(GeneratedMessage message) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(message); i++) {
+ result.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(Builder builder) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(builder); i++) {
+ result.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessage message) {
+ return get(message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return get(builder);
+ }
+
+ @Override
+ public void set(Builder builder, Object value) {
+ clear(builder);
+ for (Object entry : (List) value) {
+ addRepeated(builder, entry);
+ }
+ }
+
+ @Override
+ public Object getRepeated(GeneratedMessage message, int index) {
+ return getMapField(message).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeated(Builder builder, int index) {
+ return getMapField(builder).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage message, int index) {
+ return getRepeated(message, index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+
+ @Override
+ public void setRepeated(Builder builder, int index, Object value) {
+ getMutableMapField(builder).getMutableList().set(index, (Message) value);
+ }
+
+ @Override
+ public void addRepeated(Builder builder, Object value) {
+ getMutableMapField(builder).getMutableList().add((Message) value);
+ }
+
+ @Override
+ public boolean has(GeneratedMessage message) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public boolean has(Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public int getRepeatedCount(GeneratedMessage message) {
+ return getMapField(message).getList().size();
+ }
+
+ @Override
+ public int getRepeatedCount(Builder builder) {
+ return getMapField(builder).getList().size();
+ }
+
+ @Override
+ public void clear(Builder builder) {
+ getMutableMapField(builder).getMutableList().clear();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder newBuilder() {
+ return mapEntryMessageDefaultInstance.newBuilderForType();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularEnumFieldAccessor
+ extends SingularFieldAccessor {
+ SingularEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+ getValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+ setValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+ }
+ }
+
+ private EnumDescriptor enumDescriptor;
+
+ private Method valueOfMethod;
+ private Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getValueMethod;
+ private Method getValueMethodBuilder;
+ private Method setValueMethod;
+
+ @Override
+ public Object get(final GeneratedMessage message) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethod, message);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(message));
+ }
+
+ @Override
+ public Object get(final GeneratedMessage.Builder builder) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(builder));
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.set(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ private static final class RepeatedEnumFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getRepeatedValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
+ getRepeatedValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
+ setRepeatedValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
+ addRepeatedValueMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
+ }
+ }
+ private EnumDescriptor enumDescriptor;
+
+ private final Method valueOfMethod;
+ private final Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getRepeatedValueMethod;
+ private Method getRepeatedValueMethodBuilder;
+ private Method setRepeatedValueMethod;
+ private Method addRepeatedValueMethod;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessage message) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(message);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessage.Builder builder) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(builder);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ public Object getRepeated(final GeneratedMessage message,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(message, index));
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessage.Builder builder,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(builder, index));
+ }
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setRepeatedValueMethod, builder, index,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+ value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(addRepeatedValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ /**
+ * Field accessor for string fields.
+ *
+ * <p>This class makes getFooBytes() and setFooBytes() available for
+ * reflection API so that reflection based serialize/parse functions can
+ * access the raw bytes of the field to preserve non-UTF8 bytes in the
+ * string.
+ *
+ * <p>This ensures the serialize/parse round-trip safety, which is important
+ * for servers which forward messages.
+ */
+ private static final class SingularStringFieldAccessor
+ extends SingularFieldAccessor {
+ SingularStringFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+ getBytesMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "Bytes");
+ getBytesMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Bytes");
+ setBytesMethodBuilder = getMethodOrDie(builderClass,
+ "set" + camelCaseName + "Bytes", ByteString.class);
+ }
+
+ private final Method getBytesMethod;
+ private final Method getBytesMethodBuilder;
+ private final Method setBytesMethodBuilder;
+
+ @Override
+ public Object getRaw(final GeneratedMessage message) {
+ return invokeOrDie(getBytesMethod, message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessage.Builder builder) {
+ return invokeOrDie(getBytesMethodBuilder, builder);
+ }
+
+ @Override
+ public void set(GeneratedMessage.Builder builder, Object value) {
+ if (value instanceof ByteString) {
+ invokeOrDie(setBytesMethodBuilder, builder, value);
+ } else {
+ super.set(builder, value);
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularMessageFieldAccessor
+ extends SingularFieldAccessor {
+ SingularMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).buildPartial();
+ }
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ super.set(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
+ return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+ }
+ }
+
+ private static final class RepeatedMessageFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessage> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Builder", Integer.TYPE);
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).build();
+ }
+ }
+
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ super.setRepeated(builder, index, coerceType(value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ super.addRepeated(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(
+ final GeneratedMessage.Builder builder, final int index) {
+ return (Message.Builder) invokeOrDie(
+ getBuilderMethodBuilder, builder, index);
+ }
+ }
+ }
+
+ /**
+ * Replaces this object in the output stream with a serialized form.
+ * Part of Java's serialization magic. Generated sub-classes must override
+ * this method by calling {@code return super.writeReplace();}
+ * @return a SerializedForm of this message
+ */
+ protected Object writeReplace() throws ObjectStreamException {
+ return new GeneratedMessageLite.SerializedForm(this);
+ }
+
+ /**
+ * Checks that the {@link Extension} is non-Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <MessageType extends ExtendableMessage<MessageType>, T>
+ Extension<MessageType, T> checkNotLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (extension.isLite()) {
+ throw new IllegalArgumentException("Expected non-lite extension.");
+ }
+
+ return (Extension<MessageType, T>) extension;
+ }
+
+ protected static int computeStringSize(final int fieldNumber, final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
+ } else {
+ return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static int computeStringSizeNoTag(final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ } else {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ }
+ }
+
+ protected static void writeString(
+ CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeString(fieldNumber, (String) value);
+ } else {
+ output.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static void writeStringNoTag(
+ CodedOutputStream output, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeStringNoTag((String) value);
+ } else {
+ output.writeBytesNoTag((ByteString) value);
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
new file mode 100644
index 0000000000..2d7fd33413
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -0,0 +1,2421 @@
+// 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 com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException;
+import com.google.protobuf.Internal.BooleanList;
+import com.google.protobuf.Internal.DoubleList;
+import com.google.protobuf.Internal.FloatList;
+import com.google.protobuf.Internal.IntList;
+import com.google.protobuf.Internal.LongList;
+import com.google.protobuf.Internal.ProtobufList;
+import com.google.protobuf.WireFormat.FieldType;
+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.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Lite version of {@link GeneratedMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageLite<
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
+ extends AbstractMessageLite<MessageType, BuilderType> {
+
+ /** For use by generated code only. Lazily initialized to reduce allocations. */
+ protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+
+ /** For use by generated code only. */
+ protected int memoizedSerializedSize = -1;
+
+ @Override
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final Parser<MessageType> getParserForType() {
+ return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final MessageType getDefaultInstanceForType() {
+ return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ public final BuilderType newBuilderForType() {
+ return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
+ }
+
+ /**
+ * A reflective toString function. This is primarily intended as a developer aid, while keeping
+ * binary size down. The first line of the {@code toString()} representation includes a commented
+ * version of {@code super.toString()} to act as an indicator that this should not be relied on
+ * for comparisons.
+ * <p>
+ * NOTE: This method relies on the field getter methods not being stripped or renamed by proguard.
+ * If they are, the fields will not be included in the returned string representation.
+ * <p>
+ * NOTE: This implementation is liable to change in the future, and should not be relied on in
+ * code.
+ */
+ @Override
+ public String toString() {
+ return MessageLiteToString.toString(this, super.toString());
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime
+ @Override
+ public int hashCode() {
+ if (memoizedHashCode == 0) {
+ HashCodeVisitor visitor = new HashCodeVisitor();
+ visit(visitor, (MessageType) this);
+ memoizedHashCode = visitor.hashCode;
+ }
+ return memoizedHashCode;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime
+ int hashCode(HashCodeVisitor visitor) {
+ if (memoizedHashCode == 0) {
+ int inProgressHashCode = visitor.hashCode;
+ visitor.hashCode = 0;
+ visit(visitor, (MessageType) this);
+ memoizedHashCode = visitor.hashCode;
+ visitor.hashCode = inProgressHashCode;
+ }
+ return memoizedHashCode;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ return false;
+ }
+
+ try {
+ visit(EqualsVisitor.INSTANCE, (MessageType) other);
+ } catch (NotEqualsException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Same as {@link #equals(Object)} but throws {@code NotEqualsException}.
+ */
+ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+ boolean equals(EqualsVisitor visitor, MessageLite other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ return false;
+ }
+
+ visit(visitor, (MessageType) other);
+ return true;
+ }
+
+ // The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
+ // mutable during the parsing constructor and immutable after. This allows us to avoid
+ // any unnecessary intermediary allocations while reducing the generated code size.
+
+ /**
+ * Lazily initializes unknown fields.
+ */
+ private final void ensureUnknownFieldsInitialized() {
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ }
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ *
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(int tag, CodedInputStream input) throws IOException {
+ // This will avoid the allocation of unknown fields when a group tag is encountered.
+ if (WireFormat.getTagWireType(tag) == WireFormat.WIRETYPE_END_GROUP) {
+ return false;
+ }
+
+ ensureUnknownFieldsInitialized();
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ */
+ protected void mergeVarintField(int tag, int value) {
+ ensureUnknownFieldsInitialized();
+ unknownFields.mergeVarintField(tag, value);
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field. For use by generated code only.
+ */
+ protected void mergeLengthDelimitedField(int fieldNumber, ByteString value) {
+ ensureUnknownFieldsInitialized();
+ unknownFields.mergeLengthDelimitedField(fieldNumber, value);
+ }
+
+ /**
+ * Called by subclasses to complete parsing. For use by generated code only.
+ */
+ protected void makeImmutable() {
+ dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+
+ unknownFields.makeImmutable();
+ }
+
+ @Override
+ public final boolean isInitialized() {
+ return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final BuilderType toBuilder() {
+ BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
+ builder.mergeFrom((MessageType) this);
+ return builder;
+ }
+
+ /**
+ * Defines which method path to invoke in {@link GeneratedMessageLite
+ * #dynamicMethod(MethodToInvoke, Object...)}.
+ * <p>
+ * For use by generated code only.
+ */
+ public static enum MethodToInvoke {
+ // Rely on/modify instance state
+ IS_INITIALIZED,
+ VISIT,
+ MERGE_FROM_STREAM,
+ MAKE_IMMUTABLE,
+
+ // Rely on static state
+ NEW_MUTABLE_INSTANCE,
+ NEW_BUILDER,
+ GET_DEFAULT_INSTANCE,
+ GET_PARSER;
+ }
+
+ /**
+ * A method that implements different types of operations described in {@link MethodToInvoke}.
+ * Theses different kinds of operations are required to implement message-level operations for
+ * builders in the runtime. This method bundles those operations to reduce the generated methods
+ * count.
+ * <ul>
+ * <li>{@code MERGE_FROM_STREAM} is parameterized with an {@link CodedInputStream} and
+ * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the
+ * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the
+ * implementation wraps it in a RuntimeException.
+ * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been
+ * made immutable. See {@code MAKE_IMMUTABLE}.
+ * <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to
+ * memoize. It returns {@code null} for false and the default instance for true. We optionally
+ * memoize to support the Builder case, where memoization is not desired.
+ * <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
+ * <li>{@code VISIT} is parameterized with a {@code Visitor} and a {@code MessageType} and
+ * recursively iterates through the fields side by side between this and the instance.
+ * <li>{@code MAKE_IMMUTABLE} sets all internal fields to an immutable state.
+ * </ul>
+ * This method, plus the implementation of the Builder, enables the Builder class to be proguarded
+ * away entirely on Android.
+ * <p>
+ * For use by generated code only.
+ */
+ protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
+ return dynamicMethod(method, arg0, null);
+ }
+
+ /**
+ * Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding.
+ */
+ protected Object dynamicMethod(MethodToInvoke method) {
+ return dynamicMethod(method, null, null);
+ }
+
+ void visit(Visitor visitor, MessageType other) {
+ dynamicMethod(MethodToInvoke.VISIT, visitor, other);
+ unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields);
+ }
+
+ /**
+ * Merge some unknown fields into the {@link UnknownFieldSetLite} for this
+ * message.
+ *
+ * <p>For use by generated code only.
+ */
+ protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) {
+ this.unknownFields = UnknownFieldSetLite.mutableCopyOf(this.unknownFields, unknownFields);
+ }
+
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder<
+ MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
+ BuilderType extends Builder<MessageType, BuilderType>>
+ extends AbstractMessageLite.Builder<MessageType, BuilderType> {
+
+ private final MessageType defaultInstance;
+ protected MessageType instance;
+ protected boolean isBuilt;
+
+ protected Builder(MessageType defaultInstance) {
+ this.defaultInstance = defaultInstance;
+ this.instance =
+ (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ isBuilt = false;
+ }
+
+ /**
+ * Called before any method that would mutate the builder to ensure that it correctly copies
+ * any state before the write happens to preserve immutability guarantees.
+ */
+ protected void copyOnWrite() {
+ if (isBuilt) {
+ MessageType newInstance =
+ (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ newInstance.visit(MergeFromVisitor.INSTANCE, instance);
+ instance = newInstance;
+ isBuilt = false;
+ }
+ }
+
+ @Override
+ public final boolean isInitialized() {
+ return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */);
+ }
+
+ @Override
+ public final BuilderType clear() {
+ // No need to copy on write since we're dropping the instance anyways.
+ instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clone() {
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
+ }
+
+ @Override
+ public MessageType buildPartial() {
+ if (isBuilt) {
+ return instance;
+ }
+
+ instance.makeImmutable();
+
+ isBuilt = true;
+ return instance;
+ }
+
+ @Override
+ public final MessageType build() {
+ MessageType result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @Override
+ protected BuilderType internalMergeFrom(MessageType message) {
+ return mergeFrom(message);
+ }
+
+ /** All subclasses implement this. */
+ public BuilderType mergeFrom(MessageType message) {
+ copyOnWrite();
+ instance.visit(MergeFromVisitor.INSTANCE, message);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public MessageType getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ @Override
+ public BuilderType mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ copyOnWrite();
+ try {
+ instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof IOException) {
+ throw (IOException) e.getCause();
+ }
+ throw e;
+ }
+ return (BuilderType) this;
+ }
+ }
+
+
+ // =================================================================
+ // Extensions-related stuff
+
+ /**
+ * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}.
+ */
+ public interface ExtendableMessageOrBuilder<
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends MessageLiteOrBuilder {
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ ExtensionLite<MessageType, List<Type>> extension);
+
+ /** Get the value of an extension. */
+ <Type> Type getExtension(ExtensionLite<MessageType, Type> extension);
+
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, List<Type>> extension,
+ int index);
+ }
+
+ /**
+ * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}.
+ */
+ public abstract static class ExtendableMessage<
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends GeneratedMessageLite<MessageType, BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
+
+ /**
+ * Represents the set of extensions on this message. For use by generated
+ * code only.
+ */
+ protected FieldSet<ExtensionDescriptor> extensions = FieldSet.newFieldSet();
+
+ @SuppressWarnings("unchecked")
+ protected final void mergeExtensionFields(final MessageType other) {
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
+ }
+ extensions.mergeFrom(((ExtendableMessage) other).extensions);
+ }
+
+ @Override
+ final void visit(Visitor visitor, MessageType other) {
+ super.visit(visitor, other);
+ extensions = visitor.visitExtensions(extensions, other.extensions);
+ }
+
+ /**
+ * Parse an unknown field or an extension. For use by generated code only.
+ *
+ * <p>For use by generated code only.
+ *
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected <MessageType extends MessageLite> boolean parseUnknownField(
+ MessageType defaultInstance,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ // TODO(dweis): How much bytecode would be saved by not requiring the generated code to
+ // provide the default instance?
+ GeneratedExtension<MessageType, ?> extension = extensionRegistry.findLiteExtensionByNumber(
+ defaultInstance, fieldNumber);
+
+ return parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
+ }
+
+ private boolean parseExtension(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ GeneratedExtension<?, ?> extension,
+ int tag,
+ int fieldNumber)
+ throws IOException {
+ int wireType = WireFormat.getTagWireType(tag);
+ boolean unknown = false;
+ boolean packed = false;
+ if (extension == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ false /* isPacked */)) {
+ packed = false; // Normal, unpacked value.
+ } else if (extension.descriptor.isRepeated &&
+ extension.descriptor.type.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ extension.descriptor.getLiteType(),
+ true /* isPacked */)) {
+ packed = true; // Packed value.
+ } else {
+ unknown = true; // Wrong wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
+ return parseUnknownField(tag, input);
+ }
+
+ if (packed) {
+ int length = input.readRawVarint32();
+ int limit = input.pushLimit(length);
+ if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ int rawValue = input.readEnum();
+ Object value =
+ extension.descriptor.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ Object value =
+ FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
+ extensions.addRepeatedField(extension.descriptor, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ Object value;
+ switch (extension.descriptor.getLiteJavaType()) {
+ case MESSAGE: {
+ MessageLite.Builder subBuilder = null;
+ if (!extension.descriptor.isRepeated()) {
+ MessageLite existingValue =
+ (MessageLite) extensions.getField(extension.descriptor);
+ if (existingValue != null) {
+ subBuilder = existingValue.toBuilder();
+ }
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.getMessageDefaultInstance()
+ .newBuilderForType();
+ }
+ if (extension.descriptor.getLiteType() ==
+ WireFormat.FieldType.GROUP) {
+ input.readGroup(extension.getNumber(),
+ subBuilder, extensionRegistry);
+ } else {
+ input.readMessage(subBuilder, extensionRegistry);
+ }
+ value = subBuilder.build();
+ break;
+ }
+ case ENUM:
+ int rawValue = input.readEnum();
+ value = extension.descriptor.getEnumType()
+ .findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // write it to unknown fields object.
+ if (value == null) {
+ mergeVarintField(fieldNumber, rawValue);
+ return true;
+ }
+ break;
+ default:
+ value = FieldSet.readPrimitiveField(input,
+ extension.descriptor.getLiteType(),
+ /*checkUtf8=*/ false);
+ break;
+ }
+
+ if (extension.descriptor.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ } else {
+ extensions.setField(extension.descriptor,
+ extension.singularToFieldSetType(value));
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Parse an unknown field or an extension. For use by generated code only.
+ *
+ * <p>For use by generated code only.
+ *
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected <MessageType extends MessageLite> boolean parseUnknownFieldAsMessageSet(
+ MessageType defaultInstance,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ int tag)
+ throws IOException {
+
+ if (tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
+ mergeMessageSetExtensionFromCodedStream(defaultInstance, input, extensionRegistry);
+ return true;
+ }
+
+ // TODO(dweis): Do we really want to support non message set wire format in message sets?
+ // Full runtime does... So we do for now.
+ int wireType = WireFormat.getTagWireType(tag);
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ return parseUnknownField(defaultInstance, input, extensionRegistry, tag);
+ } else {
+ // TODO(dweis): Should we throw on invalid input? Full runtime does not...
+ return input.skipField(tag);
+ }
+ }
+
+ /**
+ * Merges the message set from the input stream; requires message set wire format.
+ *
+ * @param defaultInstance the default instance of the containing message we are parsing in
+ * @param input the stream to parse from
+ * @param extensionRegistry the registry to use when parsing
+ */
+ private <MessageType extends MessageLite> void mergeMessageSetExtensionFromCodedStream(
+ MessageType defaultInstance,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ // The wire format for MessageSet is:
+ // message MessageSet {
+ // repeated group Item = 1 {
+ // required int32 typeId = 2;
+ // required bytes message = 3;
+ // }
+ // }
+ // "typeId" is the extension's field number. The extension can only be
+ // a message type, where "message" contains the encoded bytes of that
+ // message.
+ //
+ // In practice, we will probably never see a MessageSet item in which
+ // the message appears before the type ID, or where either field does not
+ // appear exactly once. However, in theory such cases are valid, so we
+ // should be prepared to accept them.
+
+ int typeId = 0;
+ ByteString rawBytes = null; // If we encounter "message" before "typeId"
+ GeneratedExtension<?, ?> extension = null;
+
+ // Read bytes from input, if we get it's type first then parse it eagerly,
+ // otherwise we store the raw bytes in a local variable.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+ typeId = input.readUInt32();
+ if (typeId != 0) {
+ extension = extensionRegistry.findLiteExtensionByNumber(defaultInstance, typeId);
+ }
+
+ } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+ if (typeId != 0) {
+ if (extension != null) {
+ // We already know the type, so we can parse directly from the
+ // input with no copying. Hooray!
+ eagerlyMergeMessageSetExtension(input, extension, extensionRegistry, typeId);
+ rawBytes = null;
+ continue;
+ }
+ }
+ // We haven't seen a type ID yet or we want parse message lazily.
+ rawBytes = input.readBytes();
+
+ } else { // Unknown tag. Skip it.
+ if (!input.skipField(tag)) {
+ break; // End of group
+ }
+ }
+ }
+ input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
+
+ // Process the raw bytes.
+ if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
+ if (extension != null) { // We known the type
+ mergeMessageSetExtensionFromBytes(rawBytes, extensionRegistry, extension);
+ } else { // We don't know how to parse this. Ignore it.
+ if (rawBytes != null) {
+ mergeLengthDelimitedField(typeId, rawBytes);
+ }
+ }
+ }
+ }
+
+ private void eagerlyMergeMessageSetExtension(
+ CodedInputStream input,
+ GeneratedExtension<?, ?> extension,
+ ExtensionRegistryLite extensionRegistry,
+ int typeId)
+ throws IOException {
+ int fieldNumber = typeId;
+ int tag = WireFormat.makeTag(typeId, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ parseExtension(input, extensionRegistry, extension, tag, fieldNumber);
+ }
+
+ private void mergeMessageSetExtensionFromBytes(
+ ByteString rawBytes,
+ ExtensionRegistryLite extensionRegistry,
+ GeneratedExtension<?, ?> extension)
+ throws IOException {
+ MessageLite.Builder subBuilder = null;
+ MessageLite existingValue = (MessageLite) extensions.getField(extension.descriptor);
+ if (existingValue != null) {
+ subBuilder = existingValue.toBuilder();
+ }
+ if (subBuilder == null) {
+ subBuilder = extension.getMessageDefaultInstance().newBuilderForType();
+ }
+ rawBytes.newCodedInput().readMessage(subBuilder, extensionRegistry);
+ MessageLite value = subBuilder.build();
+
+ extensions.setField(extension.descriptor, extension.singularToFieldSetType(value));
+ }
+
+ private void verifyExtensionContainingType(
+ final GeneratedExtension<MessageType, ?> extension) {
+ if (extension.getContainingTypeDefaultInstance() !=
+ getDefaultInstanceForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "This extension is for a different message type. Please make " +
+ "sure that you are not suppressing any generics type warnings.");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.hasField(extensionLite.descriptor);
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extension) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return extensions.getRepeatedFieldCount(extensionLite.descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ final Object value = extensions.getField(extensionLite.descriptor);
+ if (value == null) {
+ return extensionLite.defaultValue;
+ } else {
+ return (Type) extensionLite.fromFieldSetType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extension, final int index) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ return (Type) extensionLite.singularFromFieldSetType(
+ extensions.getRepeatedField(extensionLite.descriptor, index));
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ @Override
+ protected final void makeImmutable() {
+ super.makeImmutable();
+
+ extensions.makeImmutable();
+ }
+
+ /**
+ * Used by subclasses to serialize extensions. Extension ranges may be
+ * interleaved with field numbers, but we must write them in canonical
+ * (sorted by field number) order. ExtensionWriter helps us write
+ * individual ranges of extensions at once.
+ */
+ protected class ExtensionWriter {
+ // Imagine how much simpler this code would be if Java iterators had
+ // a way to get the next element without advancing the iterator.
+
+ private final Iterator<Map.Entry<ExtensionDescriptor, Object>> iter =
+ extensions.iterator();
+ private Map.Entry<ExtensionDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
+
+ private ExtensionWriter(boolean messageSetWireFormat) {
+ if (iter.hasNext()) {
+ next = iter.next();
+ }
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void writeUntil(final int end, final CodedOutputStream output)
+ throws IOException {
+ while (next != null && next.getKey().getNumber() < end) {
+ ExtensionDescriptor extension = next.getKey();
+ if (messageSetWireFormat && extension.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !extension.isRepeated()) {
+ output.writeMessageSetExtension(extension.getNumber(),
+ (MessageLite) next.getValue());
+ } else {
+ FieldSet.writeField(extension, next.getValue(), output);
+ }
+ if (iter.hasNext()) {
+ next = iter.next();
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter newExtensionWriter() {
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
+ }
+
+ /** Called by subclasses to compute the size of extensions. */
+ protected int extensionsSerializedSize() {
+ return extensions.getSerializedSize();
+ }
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
+ }
+
+ /**
+ * Lite equivalent of {@link GeneratedMessage.ExtendableBuilder}.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class ExtendableBuilder<
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends Builder<MessageType, BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType, BuilderType> {
+ protected ExtendableBuilder(MessageType defaultInstance) {
+ super(defaultInstance);
+
+ // TODO(dweis): This is kind of an unnecessary clone since we construct a
+ // new instance in the parent constructor which makes the extensions
+ // immutable. This extra allocation shouldn't matter in practice
+ // though.
+ instance.extensions = instance.extensions.clone();
+ }
+
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<ExtensionDescriptor> extensions) {
+ copyOnWrite();
+ instance.extensions = extensions;
+ }
+
+ @Override
+ protected void copyOnWrite() {
+ if (!isBuilt) {
+ return;
+ }
+
+ super.copyOnWrite();
+ instance.extensions = instance.extensions.clone();
+ }
+
+ @Override
+ public final MessageType buildPartial() {
+ if (isBuilt) {
+ return instance;
+ }
+
+ instance.extensions.makeImmutable();
+ return super.buildPartial();
+ }
+
+ private void verifyExtensionContainingType(
+ final GeneratedExtension<MessageType, ?> extension) {
+ if (extension.getContainingTypeDefaultInstance() !=
+ getDefaultInstanceForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "This extension is for a different message type. Please make " +
+ "sure that you are not suppressing any generics type warnings.");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
+ return instance.hasExtension(extension);
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extension) {
+ return instance.getExtensionCount(extension);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
+ return instance.getExtension(extension);
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extension, final int index) {
+ return instance.getExtension(extension, index);
+ }
+
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, Type> extension,
+ final Type value) {
+ GeneratedExtension<MessageType, Type> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ copyOnWrite();
+ instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value));
+ return (BuilderType) this;
+ }
+
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ copyOnWrite();
+ instance.extensions.setRepeatedField(
+ extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value));
+ return (BuilderType) this;
+ }
+
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final ExtensionLite<MessageType, List<Type>> extension,
+ final Type value) {
+ GeneratedExtension<MessageType, List<Type>> extensionLite =
+ checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ copyOnWrite();
+ instance.extensions.addRepeatedField(
+ extensionLite.descriptor, extensionLite.singularToFieldSetType(value));
+ return (BuilderType) this;
+ }
+
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final ExtensionLite<MessageType, ?> extension) {
+ GeneratedExtension<MessageType, ?> extensionLite = checkIsLite(extension);
+
+ verifyExtensionContainingType(extensionLite);
+ copyOnWrite();
+ instance.extensions.clearField(extensionLite.descriptor);
+ return (BuilderType) this;
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /** For use by generated code only. */
+ public static <ContainingType extends MessageLite, Type>
+ GeneratedExtension<ContainingType, Type>
+ newSingularGeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final Type defaultValue,
+ final MessageLite messageDefaultInstance,
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type,
+ final Class singularType) {
+ return new GeneratedExtension<ContainingType, Type>(
+ containingTypeDefaultInstance,
+ defaultValue,
+ messageDefaultInstance,
+ new ExtensionDescriptor(enumTypeMap, number, type,
+ false /* isRepeated */,
+ false /* isPacked */),
+ singularType);
+ }
+
+ /** For use by generated code only. */
+ public static <ContainingType extends MessageLite, Type>
+ GeneratedExtension<ContainingType, Type>
+ newRepeatedGeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final MessageLite messageDefaultInstance,
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type,
+ final boolean isPacked,
+ final Class singularType) {
+ @SuppressWarnings("unchecked") // Subclasses ensure Type is a List
+ Type emptyList = (Type) Collections.emptyList();
+ return new GeneratedExtension<ContainingType, Type>(
+ containingTypeDefaultInstance,
+ emptyList,
+ messageDefaultInstance,
+ new ExtensionDescriptor(
+ enumTypeMap, number, type, true /* isRepeated */, isPacked),
+ singularType);
+ }
+
+ static final class ExtensionDescriptor
+ implements FieldSet.FieldDescriptorLite<
+ ExtensionDescriptor> {
+ ExtensionDescriptor(
+ final Internal.EnumLiteMap<?> enumTypeMap,
+ final int number,
+ final WireFormat.FieldType type,
+ final boolean isRepeated,
+ final boolean isPacked) {
+ this.enumTypeMap = enumTypeMap;
+ this.number = number;
+ this.type = type;
+ this.isRepeated = isRepeated;
+ this.isPacked = isPacked;
+ }
+
+ final Internal.EnumLiteMap<?> enumTypeMap;
+ final int number;
+ final WireFormat.FieldType type;
+ final boolean isRepeated;
+ final boolean isPacked;
+
+ @Override
+ public int getNumber() {
+ return number;
+ }
+
+ @Override
+ public WireFormat.FieldType getLiteType() {
+ return type;
+ }
+
+ @Override
+ public WireFormat.JavaType getLiteJavaType() {
+ return type.getJavaType();
+ }
+
+ @Override
+ public boolean isRepeated() {
+ return isRepeated;
+ }
+
+ @Override
+ public boolean isPacked() {
+ return isPacked;
+ }
+
+ @Override
+ public Internal.EnumLiteMap<?> getEnumType() {
+ return enumTypeMap;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
+ return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
+ }
+
+
+ @Override
+ public int compareTo(ExtensionDescriptor other) {
+ return number - other.number;
+ }
+ }
+
+ // =================================================================
+
+ /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+ @SuppressWarnings("unchecked")
+ static Method getMethodOrDie(Class clazz, String name, Class... params) {
+ try {
+ return clazz.getMethod(name, params);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(
+ "Generated message class \"" + clazz.getName() +
+ "\" missing method \"" + name + "\".", e);
+ }
+ }
+
+ /** Calls invoke and throws a RuntimeException if it fails. */
+ static Object invokeOrDie(Method method, Object object, Object... params) {
+ try {
+ return method.invoke(object, params);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Couldn't use Java reflection to implement protocol message " +
+ "reflection.", e);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(
+ "Unexpected exception thrown by generated accessor method.", cause);
+ }
+ }
+ }
+
+ /**
+ * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
+ *
+ * Users should ignore the contents of this class and only use objects of
+ * this type as parameters to extension accessors and ExtensionRegistry.add().
+ */
+ public static class GeneratedExtension<
+ ContainingType extends MessageLite, Type>
+ extends ExtensionLite<ContainingType, Type> {
+
+ /**
+ * Create a new instance with the given parameters.
+ *
+ * The last parameter {@code singularType} is only needed for enum types.
+ * We store integer values for enum types in a {@link ExtendableMessage}
+ * and use Java reflection to convert an integer value back into a concrete
+ * enum object.
+ */
+ GeneratedExtension(
+ final ContainingType containingTypeDefaultInstance,
+ final Type defaultValue,
+ final MessageLite messageDefaultInstance,
+ final ExtensionDescriptor descriptor,
+ final Class singularType) {
+ // Defensive checks to verify the correct initialization order of
+ // GeneratedExtensions and their related GeneratedMessages.
+ if (containingTypeDefaultInstance == null) {
+ throw new IllegalArgumentException(
+ "Null containingTypeDefaultInstance");
+ }
+ if (descriptor.getLiteType() == WireFormat.FieldType.MESSAGE &&
+ messageDefaultInstance == null) {
+ throw new IllegalArgumentException(
+ "Null messageDefaultInstance");
+ }
+ this.containingTypeDefaultInstance = containingTypeDefaultInstance;
+ this.defaultValue = defaultValue;
+ this.messageDefaultInstance = messageDefaultInstance;
+ this.descriptor = descriptor;
+ }
+
+ final ContainingType containingTypeDefaultInstance;
+ final Type defaultValue;
+ final MessageLite messageDefaultInstance;
+ final ExtensionDescriptor descriptor;
+
+ /**
+ * Default instance of the type being extended, used to identify that type.
+ */
+ public ContainingType getContainingTypeDefaultInstance() {
+ return containingTypeDefaultInstance;
+ }
+
+ /** Get the field number. */
+ @Override
+ public int getNumber() {
+ return descriptor.getNumber();
+ }
+
+
+ /**
+ * If the extension is an embedded message or group, returns the default
+ * instance of the message.
+ */
+ @Override
+ public MessageLite getMessageDefaultInstance() {
+ return messageDefaultInstance;
+ }
+
+ @SuppressWarnings("unchecked")
+ Object fromFieldSetType(final Object value) {
+ if (descriptor.isRepeated()) {
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
+ result.add(singularFromFieldSetType(element));
+ }
+ return result;
+ } else {
+ return value;
+ }
+ } else {
+ return singularFromFieldSetType(value);
+ }
+ }
+
+ Object singularFromFieldSetType(final Object value) {
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+ return descriptor.enumTypeMap.findValueByNumber((Integer) value);
+ } else {
+ return value;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ Object toFieldSetType(final Object value) {
+ if (descriptor.isRepeated()) {
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+ final List result = new ArrayList();
+ for (final Object element : (List) value) {
+ result.add(singularToFieldSetType(element));
+ }
+ return result;
+ } else {
+ return value;
+ }
+ } else {
+ return singularToFieldSetType(value);
+ }
+ }
+
+ Object singularToFieldSetType(final Object value) {
+ if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
+ return ((Internal.EnumLite) value).getNumber();
+ } else {
+ return value;
+ }
+ }
+
+ @Override
+ public FieldType getLiteType() {
+ return descriptor.getLiteType();
+ }
+
+ @Override
+ public boolean isRepeated() {
+ return descriptor.isRepeated;
+ }
+
+ @Override
+ public Type getDefaultValue() {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * A serialized (serializable) form of the generated message. Stores the
+ * message as a class name and a byte array.
+ */
+ protected static final class SerializedForm implements Serializable {
+
+ public static SerializedForm of(MessageLite message) {
+ return new SerializedForm(message);
+ }
+
+ private static final long serialVersionUID = 0L;
+
+ private final String messageClassName;
+ private final byte[] asBytes;
+
+ /**
+ * Creates the serialized form by calling {@link com.google.protobuf.MessageLite#toByteArray}.
+ * @param regularForm the message to serialize
+ */
+ SerializedForm(MessageLite regularForm) {
+ messageClassName = regularForm.getClass().getName();
+ asBytes = regularForm.toByteArray();
+ }
+
+ /**
+ * When read from an ObjectInputStream, this method converts this object
+ * back to the regular form. Part of Java's serialization magic.
+ * @return a GeneratedMessage of the type that was serialized
+ */
+ @SuppressWarnings("unchecked")
+ protected Object readResolve() throws ObjectStreamException {
+ try {
+ Class<?> messageClass = Class.forName(messageClassName);
+ java.lang.reflect.Field defaultInstanceField =
+ messageClass.getDeclaredField("DEFAULT_INSTANCE");
+ defaultInstanceField.setAccessible(true);
+ MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
+ return defaultInstance.newBuilderForType()
+ .mergeFrom(asBytes)
+ .buildPartial();
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
+ } catch (NoSuchFieldException e) {
+ return readResolveFallback();
+ } catch (SecurityException e) {
+ throw new RuntimeException("Unable to call DEFAULT_INSTANCE in " + messageClassName, e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Unable to call parsePartialFrom", e);
+ } catch (InvalidProtocolBufferException e) {
+ throw new RuntimeException("Unable to understand proto buffer", e);
+ }
+ }
+
+ /**
+ * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1 generated code.
+ */
+ @Deprecated
+ private Object readResolveFallback() throws ObjectStreamException {
+ try {
+ Class<?> messageClass = Class.forName(messageClassName);
+ java.lang.reflect.Field defaultInstanceField =
+ messageClass.getDeclaredField("defaultInstance");
+ defaultInstanceField.setAccessible(true);
+ MessageLite defaultInstance = (MessageLite) defaultInstanceField.get(null);
+ return defaultInstance.newBuilderForType()
+ .mergeFrom(asBytes)
+ .buildPartial();
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Unable to find proto buffer class: " + messageClassName, e);
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("Unable to find defaultInstance in " + messageClassName, e);
+ } catch (SecurityException e) {
+ throw new RuntimeException("Unable to call defaultInstance in " + messageClassName, e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Unable to call parsePartialFrom", e);
+ } catch (InvalidProtocolBufferException e) {
+ throw new RuntimeException("Unable to understand proto buffer", e);
+ }
+ }
+ }
+
+ /**
+ * Checks that the {@link Extension} is Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <
+ MessageType extends ExtendableMessage<MessageType, BuilderType>,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>,
+ T>
+ GeneratedExtension<MessageType, T> checkIsLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (!extension.isLite()) {
+ throw new IllegalArgumentException("Expected a lite extension.");
+ }
+
+ return (GeneratedExtension<MessageType, T>) extension;
+ }
+
+ /**
+ * A static helper method for checking if a message is initialized, optionally memoizing.
+ * <p>
+ * For use by generated code only.
+ */
+ protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
+ T message, boolean shouldMemoize) {
+ return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null;
+ }
+
+ protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
+ message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+ }
+
+ protected static IntList emptyIntList() {
+ return IntArrayList.emptyList();
+ }
+
+ protected static IntList mutableCopy(IntList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static LongList emptyLongList() {
+ return LongArrayList.emptyList();
+ }
+
+ protected static LongList mutableCopy(LongList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static FloatList emptyFloatList() {
+ return FloatArrayList.emptyList();
+ }
+
+ protected static FloatList mutableCopy(FloatList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static DoubleList emptyDoubleList() {
+ return DoubleArrayList.emptyList();
+ }
+
+ protected static DoubleList mutableCopy(DoubleList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static BooleanList emptyBooleanList() {
+ return BooleanArrayList.emptyList();
+ }
+
+ protected static BooleanList mutableCopy(BooleanList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ protected static <E> ProtobufList<E> emptyProtobufList() {
+ return ProtobufArrayList.emptyList();
+ }
+
+ protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ /**
+ * A {@link Parser} implementation that delegates to the default instance.
+ * <p>
+ * For use by generated code only.
+ */
+ protected static class DefaultInstanceBasedParser<T extends GeneratedMessageLite<T, ?>>
+ extends AbstractParser<T> {
+
+ private T defaultInstance;
+
+ public DefaultInstanceBasedParser(T defaultInstance) {
+ this.defaultInstance = defaultInstance;
+ }
+
+ @Override
+ public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry);
+ }
+ }
+
+ /**
+ * A static helper method for parsing a partial from input using the extension registry and the
+ * instance.
+ */
+ // TODO(dweis): Should this verify that the last tag was 0?
+ static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+ T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ @SuppressWarnings("unchecked") // Guaranteed by protoc
+ T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ try {
+ result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+ result.makeImmutable();
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof InvalidProtocolBufferException) {
+ throw (InvalidProtocolBufferException) e.getCause();
+ }
+ throw e;
+ }
+ return result;
+ }
+
+ protected static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+ T defaultInstance,
+ CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parsePartialFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ /**
+ * Helper method to check if message is initialized.
+ *
+ * @throws InvalidProtocolBufferException if it is not initialized.
+ * @return The message to check.
+ */
+ private static <T extends GeneratedMessageLite<T, ?>> T checkMessageInitialized(T message)
+ throws InvalidProtocolBufferException {
+ if (message != null && !message.isInitialized()) {
+ throw message.newUninitializedMessageException()
+ .asInvalidProtocolBufferException()
+ .setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, ByteString data)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parseFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
+ }
+
+ // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
+ // ByteString.
+ private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+ T defaultInstance, ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ T message;
+ try {
+ CodedInputStream input = data.newCodedInput();
+ message = parsePartialFrom(defaultInstance, input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ // This is a special case since we want to verify that the last tag is 0. We assume we exhaust the
+ // ByteString.
+ private static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
+ T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ T message;
+ try {
+ CodedInputStream input = CodedInputStream.newInstance(data);
+ message = parsePartialFrom(defaultInstance, input, extensionRegistry);
+ try {
+ input.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ }
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, byte[] data)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(defaultInstance, data, ExtensionRegistryLite.getEmptyRegistry()));
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(parsePartialFrom(defaultInstance, data, extensionRegistry));
+ }
+
+ // Does not validate last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, InputStream input)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input),
+ ExtensionRegistryLite.getEmptyRegistry()));
+ }
+
+ // Does not validate last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(defaultInstance, CodedInputStream.newInstance(input), extensionRegistry));
+ }
+
+ // Does not validate last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, CodedInputStream input)
+ throws InvalidProtocolBufferException {
+ return parseFrom(defaultInstance, input, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ // Does not validate last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseFrom(
+ T defaultInstance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialFrom(defaultInstance, input, extensionRegistry));
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
+ T defaultInstance, InputStream input)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialDelimitedFrom(defaultInstance, input,
+ ExtensionRegistryLite.getEmptyRegistry()));
+ }
+
+ // Validates last tag.
+ protected static <T extends GeneratedMessageLite<T, ?>> T parseDelimitedFrom(
+ T defaultInstance, InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return checkMessageInitialized(
+ parsePartialDelimitedFrom(defaultInstance, input, extensionRegistry));
+ }
+
+ private static <T extends GeneratedMessageLite<T, ?>> T parsePartialDelimitedFrom(
+ T defaultInstance,
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ int size;
+ try {
+ int firstByte = input.read();
+ if (firstByte == -1) {
+ return null;
+ }
+ size = CodedInputStream.readRawVarint32(firstByte, input);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ InputStream limitedInput = new LimitedInputStream(input, size);
+ CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
+ T message = parsePartialFrom(defaultInstance, codedInput, extensionRegistry);
+ try {
+ codedInput.checkLastTagWas(0);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(message);
+ }
+ return message;
+ }
+
+ /**
+ * An abstract visitor that the generated code calls into that we use to implement various
+ * features. Fields that are not members of oneofs are always visited. Members of a oneof are only
+ * visited when they are the set oneof case value on the "other" proto. The visitOneofNotSet
+ * method is invoked if other's oneof case is not set.
+ */
+ protected interface Visitor {
+ boolean visitBoolean(boolean minePresent, boolean mine, boolean otherPresent, boolean other);
+ int visitInt(boolean minePresent, int mine, boolean otherPresent, int other);
+ double visitDouble(boolean minePresent, double mine, boolean otherPresent, double other);
+ float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other);
+ long visitLong(boolean minePresent, long mine, boolean otherPresent, long other);
+ String visitString(boolean minePresent, String mine, boolean otherPresent, String other);
+ ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other);
+
+ Object visitOneofBoolean(boolean minePresent, Object mine, Object other);
+ Object visitOneofInt(boolean minePresent, Object mine, Object other);
+ Object visitOneofDouble(boolean minePresent, Object mine, Object other);
+ Object visitOneofFloat(boolean minePresent, Object mine, Object other);
+ Object visitOneofLong(boolean minePresent, Object mine, Object other);
+ Object visitOneofString(boolean minePresent, Object mine, Object other);
+ Object visitOneofByteString(boolean minePresent, Object mine, Object other);
+ Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
+ Object visitOneofMessage(boolean minePresent, Object mine, Object other);
+ void visitOneofNotSet(boolean minePresent);
+
+ /**
+ * Message fields use null sentinals.
+ */
+ <T extends MessageLite> T visitMessage(T mine, T other);
+ LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other);
+
+ <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
+ BooleanList visitBooleanList(BooleanList mine, BooleanList other);
+ IntList visitIntList(IntList mine, IntList other);
+ DoubleList visitDoubleList(DoubleList mine, DoubleList other);
+ FloatList visitFloatList(FloatList mine, FloatList other);
+ LongList visitLongList(LongList mine, LongList other);
+ FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine, FieldSet<ExtensionDescriptor> other);
+ UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other);
+ <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other);
+ }
+
+ /**
+ * Implements equals. Throws a {@link NotEqualsException} when not equal.
+ */
+ static class EqualsVisitor implements Visitor {
+
+ static final class NotEqualsException extends RuntimeException {}
+
+ static final EqualsVisitor INSTANCE = new EqualsVisitor();
+
+ static final NotEqualsException NOT_EQUALS = new NotEqualsException();
+
+ private EqualsVisitor() {}
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ if (minePresent != otherPresent || !mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ if (minePresent != otherPresent || !mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public void visitOneofNotSet(boolean minePresent) {
+ if (minePresent) {
+ throw NOT_EQUALS;
+ }
+ }
+
+ @Override
+ public <T extends MessageLite> T visitMessage(T mine, T other) {
+ if (mine == null && other == null) {
+ return null;
+ }
+
+ if (mine == null || other == null) {
+ throw NOT_EQUALS;
+ }
+
+ ((GeneratedMessageLite<?, ?>) mine).equals(this, other);
+
+ return mine;
+ }
+
+ @Override
+ public LazyFieldLite visitLazyMessage(
+ LazyFieldLite mine, LazyFieldLite other) {
+ if (mine == null && other == null) {
+ return null;
+ }
+ if (mine == null || other == null) {
+ throw NOT_EQUALS;
+ }
+ if (mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+ }
+
+ /**
+ * Implements hashCode by accumulating state.
+ */
+ private static class HashCodeVisitor implements Visitor {
+
+ // The caller must ensure that the visitor is invoked parameterized with this and this such that
+ // other is this. This is required due to how oneof cases are handled. See the class comment
+ // on Visitor for more information.
+
+ private int hashCode = 0;
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ hashCode = (53 * hashCode) + Internal.hashBoolean(mine);
+ return mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ hashCode = (53 * hashCode) + mine;
+ return mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits(mine));
+ return mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ hashCode = (53 * hashCode) + Float.floatToIntBits(mine);
+ return mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(mine);
+ return mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashBoolean(((Boolean) mine));
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + (Integer) mine;
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits((Double) mine));
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Float.floatToIntBits((Float) mine);
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashLong((Long) mine);
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+ return visitMessage((MessageLite) mine, (MessageLite) other);
+ }
+
+ @Override
+ public void visitOneofNotSet(boolean minePresent) {
+ if (minePresent) {
+ throw new IllegalStateException(); // Can't happen if other == this.
+ }
+ }
+
+ @Override
+ public <T extends MessageLite> T visitMessage(T mine, T other) {
+ final int protoHash;
+ if (mine != null) {
+ if (mine instanceof GeneratedMessageLite) {
+ protoHash = ((GeneratedMessageLite) mine).hashCode(this);
+ } else {
+ protoHash = mine.hashCode();
+ }
+ } else {
+ protoHash = 37;
+ }
+ hashCode = (53 * hashCode) + protoHash;
+ return mine;
+ }
+
+ @Override
+ public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
+ final int protoHash;
+ if (mine != null) {
+ protoHash = mine.hashCode();
+ } else {
+ protoHash = 37;
+ }
+ hashCode = (53 * hashCode) + protoHash;
+ return mine;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+ }
+
+ /**
+ * Implements field merging semantics over the visitor interface.
+ */
+ protected static class MergeFromVisitor implements Visitor {
+
+ public static final MergeFromVisitor INSTANCE = new MergeFromVisitor();
+
+ private MergeFromVisitor() {}
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ LazyFieldLite lazy = minePresent ? (LazyFieldLite) mine : new LazyFieldLite();
+ lazy.merge((LazyFieldLite) other);
+ return lazy;
+ }
+
+ @Override
+ public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent) {
+ return visitMessage((MessageLite) mine, (MessageLite) other);
+ }
+ return other;
+ }
+
+ @Override
+ public void visitOneofNotSet(boolean minePresent) {
+ return;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime.
+ @Override
+ public <T extends MessageLite> T visitMessage(T mine, T other) {
+ if (mine != null && other != null) {
+ return (T) mine.toBuilder().mergeFrom(other).build();
+ }
+
+ return mine != null ? mine : other;
+ }
+
+ @Override
+ public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
+ if (other != null) {
+ if (mine == null) {
+ mine = new LazyFieldLite();
+ }
+ mine.merge(other);
+ }
+ return mine;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ if (mine.isImmutable()) {
+ mine = mine.clone();
+ }
+ mine.mergeFrom(other);
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ return other == UnknownFieldSetLite.getDefaultInstance()
+ ? mine : UnknownFieldSetLite.mutableCopyOf(mine, other);
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ if (!other.isEmpty()) {
+ if (!mine.isMutable()) {
+ mine = mine.mutableCopy();
+ }
+ mine.mergeFrom(other);
+ }
+ return mine;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
new file mode 100644
index 0000000000..fd051e751d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -0,0 +1,2842 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+// In opensource protobuf, we have versioned this GeneratedMessageV3 class to GeneratedMessageV3V3 and
+// in the future may have GeneratedMessageV3V4 etc. This allows us to change some aspects of this
+// class without breaking binary compatibility with old generated code that still subclasses
+// the old GeneratedMessageV3 class. To allow these different GeneratedMessageV3V? classes to
+// interoperate (e.g., a GeneratedMessageV3V3 object has a message extension field whose class
+// type is GeneratedMessageV3V4), these classes still share a common parent class AbstarctMessage
+// and are using the same GeneratedMessage.GeneratedExtension class for extension definitions.
+// Since this class becomes GeneratedMessageV3V? in opensource, we have to add an import here
+// to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in
+// this file is also excluded from opensource to avoid conflict.
+import com.google.protobuf.GeneratedMessage.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.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * All generated protocol message classes extend this class. This class
+ * implements most of the Message and Builder interfaces using Java reflection.
+ * Users can ignore this class and pretend that generated messages implement
+ * the Message interface directly.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public abstract class GeneratedMessageV3 extends AbstractMessage
+ implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ */
+ protected static boolean alwaysUseFieldBuilders = false;
+
+ /** For use by generated code only. */
+ protected UnknownFieldSet unknownFields;
+
+ protected GeneratedMessageV3() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ }
+
+ protected GeneratedMessageV3(Builder<?> builder) {
+ unknownFields = builder.getUnknownFields();
+ }
+
+ @Override
+ public Parser<? extends GeneratedMessageV3> getParserForType() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * For testing. Allows a test to disable the optimization that avoids using
+ * field builders for nested messages until they are requested. By disabling
+ * this optimization, existing tests can be reused to test the field builders.
+ * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+ */
+ static void enableAlwaysUseFieldBuildersForTesting() {
+ alwaysUseFieldBuilders = true;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ /**
+ * Internal helper to return a modifiable map containing all the fields.
+ * The returned Map is modifialbe so that the caller can add additional
+ * extension fields to implement {@link #getAllFields()}.
+ *
+ * @param getBytesForString whether to generate ByteString for string fields
+ */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable(
+ boolean getBytesForString) {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
+ }
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
+ } else {
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
+ }
+ }
+ // Add the field to the map
+ if (getBytesForString && field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ result.put(field, getFieldRaw(field));
+ } else {
+ result.put(field, getField(field));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) && !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ false));
+ }
+
+ /**
+ * Returns a collection of all the fields in this message which are set
+ * and their corresponding values. A singular ("required" or "optional")
+ * field is set iff hasField() returns true for that field. A "repeated"
+ * field is set iff getRepeatedFieldCount() is greater than zero. The
+ * values are exactly what would be returned by calling
+ * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map
+ * is guaranteed to be a sorted map, so iterating over it will return fields
+ * in order by field number.
+ */
+ Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ return Collections.unmodifiableMap(
+ getAllFieldsMutable(/* getBytesForString = */ true));
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).get(this);
+ }
+
+ /**
+ * Obtains the value of the given field, or the default value if it is
+ * not set. For primitive fields, the boxed primitive value is returned.
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned. For present string fields, a
+ * ByteString is returned representing the bytes that the field contains.
+ */
+ Object getFieldRaw(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getRaw(this);
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ throw new UnsupportedOperationException(
+ "This is supposed to be overridden by subclasses.");
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ 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);
+ }
+
+ @Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ memoizedSize = MessageReflection.getSerializedSize(
+ this, getAllFieldsRaw());
+ return memoizedSize;
+ }
+
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ protected void makeExtensionsImmutable() {
+ // Noop for messages without extensions.
+ }
+
+ /**
+ * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
+ * interface to AbstractMessage in order to versioning GeneratedMessageV3 but
+ * this move breaks binary compatibility for AppEngine. After AppEngine is
+ * fixed we can exlude this from google3.
+ */
+ protected interface BuilderParent extends AbstractMessage.BuilderParent {}
+
+ /**
+ * TODO(xiaofeng): remove this together with GeneratedMessageV3.BuilderParent.
+ */
+ protected abstract Message.Builder newBuilderForType(BuilderParent parent);
+
+ @Override
+ protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
+ return newBuilderForType(new BuilderParent() {
+ @Override
+ public void markDirty() {
+ parent.markDirty();
+ }
+ });
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public abstract static class Builder <BuilderType extends Builder<BuilderType>>
+ extends AbstractMessage.Builder<BuilderType> {
+
+ private BuilderParent builderParent;
+
+ private BuilderParentImpl meAsParent;
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See GeneratedMessageV3.BuilderListener.
+ private boolean isClean;
+
+ private UnknownFieldSet unknownFields =
+ UnknownFieldSet.getDefaultInstance();
+
+ protected Builder() {
+ this(null);
+ }
+
+ protected Builder(BuilderParent builderParent) {
+ this.builderParent = builderParent;
+ }
+
+ @Override
+ void dispose() {
+ builderParent = null;
+ }
+
+ /**
+ * Called by the subclass when a message is built.
+ */
+ protected void onBuilt() {
+ if (builderParent != null) {
+ markClean();
+ }
+ }
+
+ /**
+ * Called by the subclass or a builder to notify us that a message was
+ * built and may be cached and therefore invalidations are needed.
+ */
+ @Override
+ protected void markClean() {
+ this.isClean = true;
+ }
+
+ /**
+ * Gets whether invalidations are needed
+ *
+ * @return whether invalidations are needed
+ */
+ protected boolean isClean() {
+ return isClean;
+ }
+
+ @Override
+ public BuilderType clone() {
+ BuilderType builder =
+ (BuilderType) getDefaultInstanceForType().newBuilderForType();
+ builder.mergeFrom(buildPartial());
+ return builder;
+ }
+
+ /**
+ * Called by the initialization and clear code paths to allow subclasses to
+ * reset any of their builtin fields back to the initial values.
+ */
+ @Override
+ public BuilderType clear() {
+ unknownFields = UnknownFieldSet.getDefaultInstance();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /**
+ * Get the FieldAccessorTable for this type. We can't have the message
+ * class pass this in to the constructor because of bootstrapping trouble
+ * with DescriptorProtos.
+ */
+ protected abstract FieldAccessorTable internalGetFieldAccessorTable();
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return internalGetFieldAccessorTable().descriptor;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ return Collections.unmodifiableMap(getAllFieldsMutable());
+ }
+
+ /** Internal helper which returns a mutable map. */
+ private Map<FieldDescriptor, Object> getAllFieldsMutable() {
+ final TreeMap<FieldDescriptor, Object> result =
+ new TreeMap<FieldDescriptor, Object>();
+ final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
+ final List<FieldDescriptor> fields = descriptor.getFields();
+
+ for (int i = 0; i < fields.size(); i++) {
+ FieldDescriptor field = fields.get(i);
+ final OneofDescriptor oneofDescriptor = field.getContainingOneof();
+
+ /*
+ * If the field is part of a Oneof, then at maximum one field in the Oneof is set
+ * and it is not repeated. There is no need to iterate through the others.
+ */
+ if (oneofDescriptor != null) {
+ // Skip other fields in the Oneof we know are not set
+ i += oneofDescriptor.getFieldCount() - 1;
+ if (!hasOneof(oneofDescriptor)) {
+ // If no field is set in the Oneof, skip all the fields in the Oneof
+ continue;
+ }
+ // Get the pointer to the only field which is set in the Oneof
+ field = getOneofFieldDescriptor(oneofDescriptor);
+ } else {
+ // If we are not in a Oneof, we need to check if the field is set and if it is repeated
+ if (field.isRepeated()) {
+ final List<?> value = (List<?>) getField(field);
+ if (!value.isEmpty()) {
+ result.put(field, value);
+ }
+ continue;
+ }
+ if (!hasField(field)) {
+ continue;
+ }
+ }
+ // Add the field to the map
+ result.put(field, getField(field));
+ }
+ return result;
+ }
+
+ @Override
+ public Message.Builder newBuilderForField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).newBuilder();
+ }
+
+ @Override
+ public Message.Builder getFieldBuilder(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).getBuilder(this);
+ }
+
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
+ return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
+ this, index);
+ }
+
+ @Override
+ public boolean hasOneof(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).has(this);
+ }
+
+ @Override
+ public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
+ return internalGetFieldAccessorTable().getOneof(oneof).get(this);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field).has(this);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ Object object = internalGetFieldAccessorTable().getField(field).get(this);
+ if (field.isRepeated()) {
+ // The underlying list object is still modifiable at this point.
+ // Make sure not to expose the modifiable list to the caller.
+ return Collections.unmodifiableList((List) object);
+ } else {
+ return object;
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).set(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ internalGetFieldAccessorTable().getField(field).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType clearOneof(final OneofDescriptor oneof) {
+ internalGetFieldAccessorTable().getOneof(oneof).clear(this);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeatedCount(this);
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
+ return internalGetFieldAccessorTable().getField(field)
+ .getRepeated(this, index);
+ }
+
+ @Override
+ public BuilderType setRepeatedField(
+ final FieldDescriptor field, final int index, final Object value) {
+ internalGetFieldAccessorTable().getField(field)
+ .setRepeated(this, index, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
+ internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
+ this.unknownFields = unknownFields;
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public BuilderType mergeUnknownFields(
+ final UnknownFieldSet unknownFields) {
+ this.unknownFields =
+ UnknownFieldSet.newBuilder(this.unknownFields)
+ .mergeFrom(unknownFields)
+ .build();
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ for (final FieldDescriptor field : getDescriptorForType().getFields()) {
+ // Check that all required fields are present.
+ if (field.isRequired()) {
+ if (!hasField(field)) {
+ return false;
+ }
+ }
+ // Check that embedded messages are initialized.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ @SuppressWarnings("unchecked") final
+ List<Message> messageList = (List<Message>) getField(field);
+ for (final Message element : messageList) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (hasField(field) &&
+ !((Message) getField(field)).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final UnknownFieldSet getUnknownFields() {
+ return unknownFields;
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ /**
+ * Implementation of {@link BuilderParent} for giving to our children. This
+ * small inner class makes it so we don't publicly expose the BuilderParent
+ * methods.
+ */
+ private class BuilderParentImpl implements BuilderParent {
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+ }
+
+ /**
+ * Gets the {@link BuilderParent} for giving to our children.
+ * @return The builder parent for our children.
+ */
+ protected BuilderParent getParentForChildren() {
+ if (meAsParent == null) {
+ meAsParent = new BuilderParentImpl();
+ }
+ return meAsParent;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ protected final void onChanged() {
+ if (isClean && builderParent != null) {
+ builderParent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"unused", "rawtypes"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /** 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
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+ }
+
+ // =================================================================
+ // Extensions-related stuff
+
+ public interface ExtendableMessageOrBuilder<
+ MessageType extends ExtendableMessage> extends MessageOrBuilder {
+ // Re-define for return type covariance.
+ @Override
+ Message getDefaultInstanceForType();
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ ExtensionLite<MessageType, List<Type>> extension);
+
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, Type> extension);
+
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ ExtensionLite<MessageType, List<Type>> extension,
+ int index);
+
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ Extension<MessageType, Type> extension);
+ /** Check if a singular extension is present. */
+ <Type> boolean hasExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ Extension<MessageType, List<Type>> extension);
+ /** Get the number of elements in a repeated extension. */
+ <Type> int getExtensionCount(
+ GeneratedExtension<MessageType, List<Type>> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, Type> extension);
+ /** Get the value of an extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, Type> extension);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ Extension<MessageType, List<Type>> extension,
+ int index);
+ /** Get one element of a repeated extension. */
+ <Type> Type getExtension(
+ GeneratedExtension<MessageType, List<Type>> extension,
+ int index);
+ }
+
+ /**
+ * Generated message classes for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "has", "get", and "getCount" -- but for extensions. The extensions
+ * are identified using instances of the class {@link GeneratedExtension};
+ * the protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo = getFoo();
+ * int i = foo.getExtension(MyProto.bar);
+ * </pre>
+ *
+ * <p>See also {@link ExtendableBuilder}.
+ */
+ public abstract static class ExtendableMessage<
+ MessageType extends ExtendableMessage>
+ extends GeneratedMessageV3
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final FieldSet<FieldDescriptor> extensions;
+
+ protected ExtendableMessage() {
+ this.extensions = FieldSet.newFieldSet();
+ }
+
+ protected ExtendableMessage(
+ ExtendableBuilder<MessageType, ?> builder) {
+ super(builder);
+ this.extensions = builder.buildExtensions();
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ @SuppressWarnings("unchecked")
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ @Override
+ protected boolean parseUnknownField(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.ExtensionAdapter(extensions), tag);
+ }
+
+
+ /**
+ * Used by parsing constructors in generated classes.
+ */
+ @Override
+ protected void makeExtensionsImmutable() {
+ extensions.makeImmutable();
+ }
+
+ /**
+ * Used by subclasses to serialize extensions. Extension ranges may be
+ * interleaved with field numbers, but we must write them in canonical
+ * (sorted by field number) order. ExtensionWriter helps us write
+ * individual ranges of extensions at once.
+ */
+ protected class ExtensionWriter {
+ // Imagine how much simpler this code would be if Java iterators had
+ // a way to get the next element without advancing the iterator.
+
+ private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
+ extensions.iterator();
+ private Map.Entry<FieldDescriptor, Object> next;
+ private final boolean messageSetWireFormat;
+
+ private ExtensionWriter(final boolean messageSetWireFormat) {
+ if (iter.hasNext()) {
+ next = iter.next();
+ }
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void writeUntil(final int end, final CodedOutputStream output)
+ throws IOException {
+ while (next != null && next.getKey().getNumber() < end) {
+ FieldDescriptor descriptor = next.getKey();
+ if (messageSetWireFormat && descriptor.getLiteJavaType() ==
+ WireFormat.JavaType.MESSAGE &&
+ !descriptor.isRepeated()) {
+ if (next instanceof LazyField.LazyEntry<?>) {
+ output.writeRawMessageSetExtension(descriptor.getNumber(),
+ ((LazyField.LazyEntry<?>) next).getField().toByteString());
+ } else {
+ output.writeMessageSetExtension(descriptor.getNumber(),
+ (Message) next.getValue());
+ }
+ } else {
+ // TODO(xiangl): Taken care of following code, it may cause
+ // problem when we use LazyField for normal fields/extensions.
+ // Due to the optional field can be duplicated at the end of
+ // serialized bytes, which will make the serialized size change
+ // after lazy field parsed. So when we use LazyField globally,
+ // we need to change the following write method to write cached
+ // bytes directly rather than write the parsed message.
+ FieldSet.writeField(descriptor, next.getValue(), output);
+ }
+ if (iter.hasNext()) {
+ next = iter.next();
+ } else {
+ next = null;
+ }
+ }
+ }
+ }
+
+ protected ExtensionWriter newExtensionWriter() {
+ return new ExtensionWriter(false);
+ }
+ protected ExtensionWriter newMessageSetExtensionWriter() {
+ return new ExtensionWriter(true);
+ }
+
+ /** Called by subclasses to compute the size of extensions. */
+ protected int extensionsSerializedSize() {
+ return extensions.getSerializedSize();
+ }
+ protected int extensionsSerializedSizeAsMessageSet() {
+ return extensions.getMessageSetSerializedSize();
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ protected Map<FieldDescriptor, Object> getExtensionFields() {
+ return extensions.getAllFields();
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFieldsRaw() {
+ final Map<FieldDescriptor, Object> result =
+ super.getAllFieldsMutable(/* getBytesForString = */ false);
+ result.putAll(getExtensionFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.isRepeated()) {
+ return Collections.emptyList();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ /**
+ * Generated message builders for message types that contain extension ranges
+ * subclass this.
+ *
+ * <p>This class implements type-safe accessors for extensions. They
+ * implement all the same operations that you can do with normal fields --
+ * e.g. "get", "set", and "add" -- but for extensions. The extensions are
+ * identified using instances of the class {@link GeneratedExtension}; the
+ * protocol compiler generates a static instance of this class for every
+ * extension in its input. Through the magic of generics, all is made
+ * type-safe.
+ *
+ * <p>For example, imagine you have the {@code .proto} file:
+ *
+ * <pre>
+ * option java_class = "MyProto";
+ *
+ * message Foo {
+ * extensions 1000 to max;
+ * }
+ *
+ * extend Foo {
+ * optional int32 bar;
+ * }
+ * </pre>
+ *
+ * <p>Then you might write code like:
+ *
+ * <pre>
+ * MyProto.Foo foo =
+ * MyProto.Foo.newBuilder()
+ * .setExtension(MyProto.bar, 123)
+ * .build();
+ * </pre>
+ *
+ * <p>See also {@link ExtendableMessage}.
+ */
+ @SuppressWarnings("unchecked")
+ public abstract static class ExtendableBuilder<
+ MessageType extends ExtendableMessage,
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+ extends Builder<BuilderType>
+ implements ExtendableMessageOrBuilder<MessageType> {
+
+ private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
+
+ protected ExtendableBuilder() {}
+
+ protected ExtendableBuilder(
+ BuilderParent parent) {
+ super(parent);
+ }
+
+ // For immutable message conversion.
+ void internalSetExtensionSet(FieldSet<FieldDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
+ @Override
+ public BuilderType clear() {
+ extensions = FieldSet.emptySet();
+ return super.clear();
+ }
+
+ private void ensureExtensionsIsMutable() {
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
+ }
+ }
+
+ private void verifyExtensionContainingType(
+ final Extension<MessageType, ?> extension) {
+ if (extension.getDescriptor().getContainingType() !=
+ getDescriptorForType()) {
+ // This can only happen if someone uses unchecked operations.
+ throw new IllegalArgumentException(
+ "Extension is for type \"" +
+ extension.getDescriptor().getContainingType().getFullName() +
+ "\" which does not match message type \"" +
+ getDescriptorForType().getFullName() + "\".");
+ }
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ return extensions.hasField(extension.getDescriptor());
+ }
+
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final ExtensionLite<MessageType, List<Type>> extensionLite) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ return extensions.getRepeatedFieldCount(descriptor);
+ }
+
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ final Object value = extensions.getField(descriptor);
+ if (value == null) {
+ if (descriptor.isRepeated()) {
+ return (Type) Collections.emptyList();
+ } else if (descriptor.getJavaType() ==
+ FieldDescriptor.JavaType.MESSAGE) {
+ return (Type) extension.getMessageDefaultInstance();
+ } else {
+ return (Type) extension.fromReflectionType(
+ descriptor.getDefaultValue());
+ }
+ } else {
+ return (Type) extension.fromReflectionType(value);
+ }
+ }
+
+ /** Get one element of a repeated extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ FieldDescriptor descriptor = extension.getDescriptor();
+ return (Type) extension.singularFromReflectionType(
+ extensions.getRepeatedField(descriptor, index));
+ }
+
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, Type> extensionLite,
+ final Type value) {
+ Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setField(descriptor, extension.toReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final int index, final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.setRepeatedField(
+ descriptor, index,
+ extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final ExtensionLite<MessageType, List<Type>> extensionLite,
+ final Type value) {
+ Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ final FieldDescriptor descriptor = extension.getDescriptor();
+ extensions.addRepeatedField(
+ descriptor, extension.singularToReflectionType(value));
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final ExtensionLite<MessageType, ?> extensionLite) {
+ Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+
+ verifyExtensionContainingType(extension);
+ ensureExtensionsIsMutable();
+ extensions.clearField(extension.getDescriptor());
+ onChanged();
+ return (BuilderType) this;
+ }
+
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Check if a singular extension is present. */
+ @Override
+ public final <Type> boolean hasExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return hasExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final Extension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the number of elements in a repeated extension. */
+ @Override
+ public final <Type> int getExtensionCount(
+ final GeneratedExtension<MessageType, List<Type>> extension) {
+ return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, Type> extension) {
+ return getExtension((ExtensionLite<MessageType, Type>) extension);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final Extension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Get the value of an extension. */
+ @Override
+ public final <Type> Type getExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
+ return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+ }
+ /** Set the value of an extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of an extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, Type> extension, final Type value) {
+ return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public final <Type> BuilderType setExtension(
+ final Extension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Set the value of one element of a repeated extension. */
+ public <Type> BuilderType setExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension,
+ final int index, final Type value) {
+ return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+ }
+ /** Append a value to a repeated extension. */
+ public final <Type> BuilderType addExtension(
+ final Extension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Append a value to a repeated extension. */
+ public <Type> BuilderType addExtension(
+ final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
+ return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+ }
+ /** Clear an extension. */
+ public final <Type> BuilderType clearExtension(
+ final Extension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+ /** Clear an extension. */
+ public <Type> BuilderType clearExtension(
+ final GeneratedExtension<MessageType, ?> extension) {
+ return clearExtension((ExtensionLite<MessageType, ?>) extension);
+ }
+
+ /** Called by subclasses to check if all extensions are initialized. */
+ protected boolean extensionsAreInitialized() {
+ return extensions.isInitialized();
+ }
+
+ /**
+ * Called by the build code path to create a copy of the extensions for
+ * building the message.
+ */
+ private FieldSet<FieldDescriptor> buildExtensions() {
+ extensions.makeImmutable();
+ return extensions;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return super.isInitialized() && extensionsAreInitialized();
+ }
+
+ /**
+ * Called by subclasses to parse an unknown field or an extension.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ @Override
+ protected boolean parseUnknownField(
+ final CodedInputStream input,
+ final UnknownFieldSet.Builder unknownFields,
+ final ExtensionRegistryLite extensionRegistry,
+ final int tag) throws IOException {
+ return MessageReflection.mergeFieldFrom(
+ input, unknownFields, extensionRegistry, getDescriptorForType(),
+ new MessageReflection.BuilderAdapter(this), tag);
+ }
+
+ // ---------------------------------------------------------------
+ // Reflection
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final Map<FieldDescriptor, Object> result = super.getAllFieldsMutable();
+ result.putAll(extensions.getAllFields());
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public Object getField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ final Object value = extensions.getField(field);
+ if (value == null) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Lacking an ExtensionRegistry, we have no way to determine the
+ // extension's real type, so we return a DynamicMessage.
+ return DynamicMessage.getDefaultInstance(field.getMessageType());
+ } else {
+ return field.getDefaultValue();
+ }
+ } else {
+ return value;
+ }
+ } else {
+ return super.getField(field);
+ }
+ }
+
+ @Override
+ public int getRepeatedFieldCount(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedFieldCount(field);
+ } else {
+ return super.getRepeatedFieldCount(field);
+ }
+ }
+
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field,
+ final int index) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.getRepeatedField(field, index);
+ } else {
+ return super.getRepeatedField(field, index);
+ }
+ }
+
+ @Override
+ public boolean hasField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ return extensions.hasField(field);
+ } else {
+ return super.hasField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setField(field, value);
+ }
+ }
+
+ @Override
+ public BuilderType clearField(final FieldDescriptor field) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.clearField(field);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.clearField(field);
+ }
+ }
+
+ @Override
+ public BuilderType setRepeatedField(final FieldDescriptor field,
+ final int index, final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.setRepeatedField(field, index, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.setRepeatedField(field, index, value);
+ }
+ }
+
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field,
+ final Object value) {
+ if (field.isExtension()) {
+ verifyContainingType(field);
+ ensureExtensionsIsMutable();
+ extensions.addRepeatedField(field, value);
+ onChanged();
+ return (BuilderType) this;
+ } else {
+ return super.addRepeatedField(field, value);
+ }
+ }
+
+ protected final void mergeExtensionFields(final ExtendableMessage other) {
+ ensureExtensionsIsMutable();
+ extensions.mergeFrom(other.extensions);
+ onChanged();
+ }
+
+ private void verifyContainingType(final FieldDescriptor field) {
+ if (field.getContainingType() != getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ }
+ }
+ }
+
+ // -----------------------------------------------------------------
+
+ /**
+ * Gets the descriptor for an extension. The implementation depends on whether
+ * the extension is scoped in the top level of a file or scoped in a Message.
+ */
+ static interface ExtensionDescriptorRetriever {
+ FieldDescriptor getDescriptor();
+ }
+
+
+ // =================================================================
+
+ /** Calls Class.getMethod and throws a RuntimeException if it fails. */
+ @SuppressWarnings("unchecked")
+ private static Method getMethodOrDie(
+ final Class clazz, final String name, final Class... params) {
+ try {
+ return clazz.getMethod(name, params);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(
+ "Generated message class \"" + clazz.getName() +
+ "\" missing method \"" + name + "\".", e);
+ }
+ }
+
+ /** Calls invoke and throws a RuntimeException if it fails. */
+ private static Object invokeOrDie(
+ final Method method, final Object object, final Object... params) {
+ try {
+ return method.invoke(object, params);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(
+ "Couldn't use Java reflection to implement protocol message " +
+ "reflection.", e);
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(
+ "Unexpected exception thrown by generated accessor method.", cause);
+ }
+ }
+ }
+
+ /**
+ * Gets the map field with the given field number. This method should be
+ * overridden in the generated message class if the message contains map
+ * fields.
+ *
+ * Unlike other field types, reflection support for map fields can't be
+ * implemented based on generated public API because we need to access a
+ * map field as a list in reflection API but the generated API only allows
+ * us to access it as a map. This method returns the underlying map field
+ * directly and thus enables us to access the map field as a list.
+ */
+ @SuppressWarnings({"rawtypes", "unused"})
+ protected MapField internalGetMapField(int fieldNumber) {
+ // Note that we can't use descriptor names here because this method will
+ // be called when descriptor is being initialized.
+ throw new RuntimeException(
+ "No map fields found in " + getClass().getName());
+ }
+
+ /**
+ * Users should ignore this class. This class provides the implementation
+ * with access to the fields of a message object using Java reflection.
+ */
+ public static final class FieldAccessorTable {
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class. Only
+ * one FieldAccessorTable should ever be constructed per class.
+ *
+ * @param descriptor The type's descriptor.
+ * @param camelCaseNames The camelcase names of all fields in the message.
+ * These are used to derive the accessor method names.
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this(descriptor, camelCaseNames);
+ ensureFieldAccessorsInitialized(messageClass, builderClass);
+ }
+
+ /**
+ * Construct a FieldAccessorTable for a particular message class without
+ * initializing FieldAccessors.
+ */
+ public FieldAccessorTable(
+ final Descriptor descriptor,
+ final String[] camelCaseNames) {
+ this.descriptor = descriptor;
+ this.camelCaseNames = camelCaseNames;
+ fields = new FieldAccessor[descriptor.getFields().size()];
+ oneofs = new OneofAccessor[descriptor.getOneofs().size()];
+ initialized = false;
+ }
+
+ /**
+ * Ensures the field accessors are initialized. This method is thread-safe.
+ *
+ * @param messageClass The message type.
+ * @param builderClass The builder type.
+ * @return this
+ */
+ public FieldAccessorTable ensureFieldAccessorsInitialized(
+ Class<? extends GeneratedMessageV3> messageClass,
+ Class<? extends Builder> builderClass) {
+ if (initialized) { return this; }
+ synchronized (this) {
+ if (initialized) { return this; }
+ int fieldsSize = fields.length;
+ for (int i = 0; i < fieldsSize; i++) {
+ FieldDescriptor field = descriptor.getFields().get(i);
+ String containingOneofCamelCaseName = null;
+ if (field.getContainingOneof() != null) {
+ containingOneofCamelCaseName =
+ camelCaseNames[fieldsSize + field.getContainingOneof().getIndex()];
+ }
+ if (field.isRepeated()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isMapField()) {
+ fields[i] = new MapFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new RepeatedEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ } else {
+ fields[i] = new RepeatedFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass);
+ }
+ } else {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ fields[i] = new SingularMessageFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+ fields[i] = new SingularEnumFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
+ fields[i] = new SingularStringFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ } else {
+ fields[i] = new SingularFieldAccessor(
+ field, camelCaseNames[i], messageClass, builderClass,
+ containingOneofCamelCaseName);
+ }
+ }
+ }
+
+ int oneofsSize = oneofs.length;
+ for (int i = 0; i < oneofsSize; i++) {
+ oneofs[i] = new OneofAccessor(
+ descriptor, camelCaseNames[i + fieldsSize],
+ messageClass, builderClass);
+ }
+ initialized = true;
+ camelCaseNames = null;
+ return this;
+ }
+ }
+
+ private final Descriptor descriptor;
+ private final FieldAccessor[] fields;
+ private String[] camelCaseNames;
+ private final OneofAccessor[] oneofs;
+ private volatile boolean initialized;
+
+ /** Get the FieldAccessor for a particular field. */
+ private FieldAccessor getField(final FieldDescriptor field) {
+ if (field.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "FieldDescriptor does not match message type.");
+ } else if (field.isExtension()) {
+ // If this type had extensions, it would subclass ExtendableMessage,
+ // which overrides the reflection interface to handle extensions.
+ throw new IllegalArgumentException(
+ "This type does not have extensions.");
+ }
+ return fields[field.getIndex()];
+ }
+
+ /** Get the OneofAccessor for a particular oneof. */
+ private OneofAccessor getOneof(final OneofDescriptor oneof) {
+ if (oneof.getContainingType() != descriptor) {
+ throw new IllegalArgumentException(
+ "OneofDescriptor does not match message type.");
+ }
+ return oneofs[oneof.getIndex()];
+ }
+
+ /**
+ * Abstract interface that provides access to a single field. This is
+ * implemented differently depending on the field type and cardinality.
+ */
+ private interface FieldAccessor {
+ Object get(GeneratedMessageV3 message);
+ Object get(GeneratedMessageV3.Builder builder);
+ Object getRaw(GeneratedMessageV3 message);
+ Object getRaw(GeneratedMessageV3.Builder builder);
+ void set(Builder builder, Object value);
+ Object getRepeated(GeneratedMessageV3 message, int index);
+ Object getRepeated(GeneratedMessageV3.Builder builder, int index);
+ Object getRepeatedRaw(GeneratedMessageV3 message, int index);
+ Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index);
+ void setRepeated(Builder builder,
+ int index, Object value);
+ void addRepeated(Builder builder, Object value);
+ boolean has(GeneratedMessageV3 message);
+ boolean has(GeneratedMessageV3.Builder builder);
+ int getRepeatedCount(GeneratedMessageV3 message);
+ int getRepeatedCount(GeneratedMessageV3.Builder builder);
+ void clear(Builder builder);
+ Message.Builder newBuilder();
+ Message.Builder getBuilder(GeneratedMessageV3.Builder builder);
+ Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder,
+ int index);
+ }
+
+ /** OneofAccessor provides access to a single oneof. */
+ private static class OneofAccessor {
+ OneofAccessor(
+ final Descriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ this.descriptor = descriptor;
+ caseMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
+ caseMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ private final Descriptor descriptor;
+ private final Method caseMethod;
+ private final Method caseMethodBuilder;
+ private final Method clearMethod;
+
+ public boolean has(final GeneratedMessageV3 message) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ public FieldDescriptor get(final GeneratedMessageV3 message) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public FieldDescriptor get(GeneratedMessageV3.Builder builder) {
+ int fieldNumber = ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ if (fieldNumber > 0) {
+ return descriptor.findFieldByNumber(fieldNumber);
+ }
+ return null;
+ }
+
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ }
+
+ private static boolean supportFieldPresence(FileDescriptor file) {
+ return file.getSyntax() == FileDescriptor.Syntax.PROTO2;
+ }
+
+ // ---------------------------------------------------------------
+
+ private static class SingularFieldAccessor implements FieldAccessor {
+ SingularFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ field = descriptor;
+ isOneofField = descriptor.getContainingOneof() != null;
+ hasHasMethod = supportFieldPresence(descriptor.getFile())
+ || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
+ getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
+ getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
+ type = getMethod.getReturnType();
+ setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
+ hasMethod =
+ hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+ hasMethodBuilder =
+ hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ caseMethod = isOneofField ? getMethodOrDie(
+ messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ caseMethodBuilder = isOneofField ? getMethodOrDie(
+ builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+ }
+
+ // Note: We use Java reflection to call public methods rather than
+ // access private fields directly as this avoids runtime security
+ // checks.
+ protected final Class<?> type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method setMethod;
+ protected final Method hasMethod;
+ protected final Method hasMethodBuilder;
+ protected final Method clearMethod;
+ protected final Method caseMethod;
+ protected final Method caseMethodBuilder;
+ protected final FieldDescriptor field;
+ protected final boolean isOneofField;
+ protected final boolean hasHasMethod;
+
+ private int getOneofFieldNumber(final GeneratedMessageV3 message) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber();
+ }
+
+ private int getOneofFieldNumber(final GeneratedMessageV3.Builder builder) {
+ return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ invokeOrDie(setMethod, builder, value);
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedField() called on a singular field.");
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldRaw() called on a singular field.");
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ throw new UnsupportedOperationException(
+ "setRepeatedField() called on a singular field.");
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ throw new UnsupportedOperationException(
+ "addRepeatedField() called on a singular field.");
+ }
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(message) == field.getNumber();
+ }
+ return !get(message).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethod, message);
+ }
+ @Override
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ if (!hasHasMethod) {
+ if (isOneofField) {
+ return getOneofFieldNumber(builder) == field.getNumber();
+ }
+ return !get(builder).equals(field.getDefaultValue());
+ }
+ return (Boolean) invokeOrDie(hasMethodBuilder, builder);
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldSize() called on a singular field.");
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class RepeatedFieldAccessor implements FieldAccessor {
+ protected final Class type;
+ protected final Method getMethod;
+ protected final Method getMethodBuilder;
+ protected final Method getRepeatedMethod;
+ protected final Method getRepeatedMethodBuilder;
+ protected final Method setRepeatedMethod;
+ protected final Method addRepeatedMethod;
+ protected final Method getCountMethod;
+ protected final Method getCountMethodBuilder;
+ protected final Method clearMethod;
+
+ RepeatedFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ getMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "List");
+ getMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "List");
+ getRepeatedMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+ getRepeatedMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
+ type = getRepeatedMethod.getReturnType();
+ setRepeatedMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName,
+ Integer.TYPE, type);
+ addRepeatedMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName, type);
+ getCountMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+ getCountMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+
+ clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ return invokeOrDie(getMethod, message);
+ }
+ @Override
+ public Object get(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getMethodBuilder, builder);
+ }
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return get(message);
+ }
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+ @Override
+ public void set(final Builder builder, final Object value) {
+ // Add all the elements individually. This serves two purposes:
+ // 1) Verifies that each element has the correct type.
+ // 2) Insures that the caller cannot modify the list later on and
+ // have the modifications be reflected in the message.
+ clear(builder);
+ for (final Object element : (List<?>) value) {
+ addRepeated(builder, element);
+ }
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message, final int index) {
+ return invokeOrDie(getRepeatedMethod, message, index);
+ }
+ @Override
+ public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+ return invokeOrDie(getRepeatedMethodBuilder, builder, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
+ return getRepeated(message, index);
+ }
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
+ invokeOrDie(setRepeatedMethod, builder, index, value);
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ invokeOrDie(addRepeatedMethod, builder, value);
+ }
+ @Override
+ public boolean has(final GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public boolean has(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() called on a repeated field.");
+ }
+ @Override
+ public int getRepeatedCount(final GeneratedMessageV3 message) {
+ return (Integer) invokeOrDie(getCountMethod, message);
+ }
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+ return (Integer) invokeOrDie(getCountMethodBuilder, builder);
+ }
+ @Override
+ public void clear(final Builder builder) {
+ invokeOrDie(clearMethod, builder);
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ throw new UnsupportedOperationException(
+ "newBuilderForField() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ throw new UnsupportedOperationException(
+ "getFieldBuilder() called on a non-Message type.");
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "getRepeatedFieldBuilder() called on a non-Message type.");
+ }
+ }
+
+ private static class MapFieldAccessor implements FieldAccessor {
+ MapFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ field = descriptor;
+ Method getDefaultInstanceMethod =
+ getMethodOrDie(messageClass, "getDefaultInstance");
+ MapField defaultMapField = getMapField(
+ (GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null));
+ mapEntryMessageDefaultInstance =
+ defaultMapField.getMapEntryMessageDefaultInstance();
+ }
+
+ private final FieldDescriptor field;
+ private final Message mapEntryMessageDefaultInstance;
+
+ private MapField<?, ?> getMapField(GeneratedMessageV3 message) {
+ return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMapField(GeneratedMessageV3.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
+ }
+
+ private MapField<?, ?> getMutableMapField(
+ GeneratedMessageV3.Builder builder) {
+ return (MapField<?, ?>) builder.internalGetMutableMapField(
+ field.getNumber());
+ }
+
+ private Message coerceType(Message value) {
+ if (value == null) {
+ return null;
+ }
+ if (mapEntryMessageDefaultInstance.getClass().isInstance(value)) {
+ return value;
+ }
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return mapEntryMessageDefaultInstance.toBuilder().mergeFrom(value).build();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(GeneratedMessageV3 message) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(message); i++) {
+ result.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(Builder builder) {
+ List result = new ArrayList();
+ for (int i = 0; i < getRepeatedCount(builder); i++) {
+ result.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3 message) {
+ return get(message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return get(builder);
+ }
+
+ @Override
+ public void set(Builder builder, Object value) {
+ clear(builder);
+ for (Object entry : (List) value) {
+ addRepeated(builder, entry);
+ }
+ }
+
+ @Override
+ public Object getRepeated(GeneratedMessageV3 message, int index) {
+ return getMapField(message).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeated(Builder builder, int index) {
+ return getMapField(builder).getList().get(index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
+ return getRepeated(message, index);
+ }
+
+ @Override
+ public Object getRepeatedRaw(Builder builder, int index) {
+ return getRepeated(builder, index);
+ }
+
+ @Override
+ public void setRepeated(Builder builder, int index, Object value) {
+ getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value));
+ }
+
+ @Override
+ public void addRepeated(Builder builder, Object value) {
+ getMutableMapField(builder).getMutableList().add(coerceType((Message) value));
+ }
+
+ @Override
+ public boolean has(GeneratedMessageV3 message) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public boolean has(Builder builder) {
+ throw new UnsupportedOperationException(
+ "hasField() is not supported for repeated fields.");
+ }
+
+ @Override
+ public int getRepeatedCount(GeneratedMessageV3 message) {
+ return getMapField(message).getList().size();
+ }
+
+ @Override
+ public int getRepeatedCount(Builder builder) {
+ return getMapField(builder).getList().size();
+ }
+
+ @Override
+ public void clear(Builder builder) {
+ getMutableMapField(builder).getMutableList().clear();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder newBuilder() {
+ return mapEntryMessageDefaultInstance.newBuilderForType();
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
+ throw new UnsupportedOperationException(
+ "Nested builder not supported for map fields.");
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularEnumFieldAccessor
+ extends SingularFieldAccessor {
+ SingularEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+ getValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+ setValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+ }
+ }
+
+ private EnumDescriptor enumDescriptor;
+
+ private Method valueOfMethod;
+ private Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getValueMethod;
+ private Method getValueMethodBuilder;
+ private Method setValueMethod;
+
+ @Override
+ public Object get(final GeneratedMessageV3 message) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethod, message);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(message));
+ }
+
+ @Override
+ public Object get(final GeneratedMessageV3.Builder builder) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod, super.get(builder));
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.set(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ private static final class RepeatedEnumFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedEnumFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ enumDescriptor = descriptor.getEnumType();
+
+ valueOfMethod = getMethodOrDie(type, "valueOf",
+ EnumValueDescriptor.class);
+ getValueDescriptorMethod =
+ getMethodOrDie(type, "getValueDescriptor");
+
+ supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
+ if (supportUnknownEnumValue) {
+ getRepeatedValueMethod =
+ getMethodOrDie(messageClass, "get" + camelCaseName + "Value", int.class);
+ getRepeatedValueMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Value", int.class);
+ setRepeatedValueMethod =
+ getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class, int.class);
+ addRepeatedValueMethod =
+ getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
+ }
+ }
+ private EnumDescriptor enumDescriptor;
+
+ private final Method valueOfMethod;
+ private final Method getValueDescriptorMethod;
+
+ private boolean supportUnknownEnumValue;
+ private Method getRepeatedValueMethod;
+ private Method getRepeatedValueMethodBuilder;
+ private Method setRepeatedValueMethod;
+ private Method addRepeatedValueMethod;
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessageV3 message) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(message);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(message, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object get(final GeneratedMessageV3.Builder builder) {
+ final List newList = new ArrayList();
+ final int size = getRepeatedCount(builder);
+ for (int i = 0; i < size; i++) {
+ newList.add(getRepeated(builder, i));
+ }
+ return Collections.unmodifiableList(newList);
+ }
+
+ @Override
+ public Object getRepeated(final GeneratedMessageV3 message,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(message, index));
+ }
+ @Override
+ public Object getRepeated(final GeneratedMessageV3.Builder builder,
+ final int index) {
+ if (supportUnknownEnumValue) {
+ int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
+ return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
+ }
+ return invokeOrDie(getValueDescriptorMethod,
+ super.getRepeated(builder, index));
+ }
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(setRepeatedValueMethod, builder, index,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
+ value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ if (supportUnknownEnumValue) {
+ invokeOrDie(addRepeatedValueMethod, builder,
+ ((EnumValueDescriptor) value).getNumber());
+ return;
+ }
+ super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ /**
+ * Field accessor for string fields.
+ *
+ * <p>This class makes getFooBytes() and setFooBytes() available for
+ * reflection API so that reflection based serialize/parse functions can
+ * access the raw bytes of the field to preserve non-UTF8 bytes in the
+ * string.
+ *
+ * <p>This ensures the serialize/parse round-trip safety, which is important
+ * for servers which forward messages.
+ */
+ private static final class SingularStringFieldAccessor
+ extends SingularFieldAccessor {
+ SingularStringFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+ getBytesMethod = getMethodOrDie(messageClass,
+ "get" + camelCaseName + "Bytes");
+ getBytesMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Bytes");
+ setBytesMethodBuilder = getMethodOrDie(builderClass,
+ "set" + camelCaseName + "Bytes", ByteString.class);
+ }
+
+ private final Method getBytesMethod;
+ private final Method getBytesMethodBuilder;
+ private final Method setBytesMethodBuilder;
+
+ @Override
+ public Object getRaw(final GeneratedMessageV3 message) {
+ return invokeOrDie(getBytesMethod, message);
+ }
+
+ @Override
+ public Object getRaw(GeneratedMessageV3.Builder builder) {
+ return invokeOrDie(getBytesMethodBuilder, builder);
+ }
+
+ @Override
+ public void set(GeneratedMessageV3.Builder builder, Object value) {
+ if (value instanceof ByteString) {
+ invokeOrDie(setBytesMethodBuilder, builder, value);
+ } else {
+ super.set(builder, value);
+ }
+ }
+ }
+
+ // ---------------------------------------------------------------
+
+ private static final class SingularMessageFieldAccessor
+ extends SingularFieldAccessor {
+ SingularMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass,
+ final String containingOneofCamelCaseName) {
+ super(descriptor, camelCaseName, messageClass, builderClass,
+ containingOneofCamelCaseName);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder =
+ getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).buildPartial();
+ }
+ }
+
+ @Override
+ public void set(final Builder builder, final Object value) {
+ super.set(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+ return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
+ }
+ }
+
+ private static final class RepeatedMessageFieldAccessor
+ extends RepeatedFieldAccessor {
+ RepeatedMessageFieldAccessor(
+ final FieldDescriptor descriptor, final String camelCaseName,
+ final Class<? extends GeneratedMessageV3> messageClass,
+ final Class<? extends Builder> builderClass) {
+ super(descriptor, camelCaseName, messageClass, builderClass);
+
+ newBuilderMethod = getMethodOrDie(type, "newBuilder");
+ getBuilderMethodBuilder = getMethodOrDie(builderClass,
+ "get" + camelCaseName + "Builder", Integer.TYPE);
+ }
+
+ private final Method newBuilderMethod;
+ private final Method getBuilderMethodBuilder;
+
+ private Object coerceType(final Object value) {
+ if (type.isInstance(value)) {
+ return value;
+ } else {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
+ .mergeFrom((Message) value).build();
+ }
+ }
+
+ @Override
+ public void setRepeated(final Builder builder,
+ final int index, final Object value) {
+ super.setRepeated(builder, index, coerceType(value));
+ }
+ @Override
+ public void addRepeated(final Builder builder, final Object value) {
+ super.addRepeated(builder, coerceType(value));
+ }
+ @Override
+ public Message.Builder newBuilder() {
+ return (Message.Builder) invokeOrDie(newBuilderMethod, null);
+ }
+ @Override
+ public Message.Builder getRepeatedBuilder(
+ final GeneratedMessageV3.Builder builder, final int index) {
+ return (Message.Builder) invokeOrDie(
+ getBuilderMethodBuilder, builder, index);
+ }
+ }
+ }
+
+ /**
+ * Replaces this object in the output stream with a serialized form.
+ * Part of Java's serialization magic. Generated sub-classes must override
+ * this method by calling {@code return super.writeReplace();}
+ * @return a SerializedForm of this message
+ */
+ protected Object writeReplace() throws ObjectStreamException {
+ return new GeneratedMessageLite.SerializedForm(this);
+ }
+
+ /**
+ * Checks that the {@link Extension} is non-Lite and returns it as a
+ * {@link GeneratedExtension}.
+ */
+ private static <MessageType extends ExtendableMessage<MessageType>, T>
+ Extension<MessageType, T> checkNotLite(
+ ExtensionLite<MessageType, T> extension) {
+ if (extension.isLite()) {
+ throw new IllegalArgumentException("Expected non-lite extension.");
+ }
+
+ return (Extension<MessageType, T>) extension;
+ }
+
+ protected static int computeStringSize(final int fieldNumber, final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
+ } else {
+ return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static int computeStringSizeNoTag(final Object value) {
+ if (value instanceof String) {
+ return CodedOutputStream.computeStringSizeNoTag((String) value);
+ } else {
+ return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ }
+ }
+
+ protected static void writeString(
+ CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeString(fieldNumber, (String) value);
+ } else {
+ output.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ protected static void writeStringNoTag(
+ CodedOutputStream output, final Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeStringNoTag((String) value);
+ } else {
+ output.writeBytesNoTag((ByteString) value);
+ }
+ }
+
+ protected static <V> void serializeIntegerMapTo(
+ CodedOutputStream out,
+ MapField<Integer, V> field,
+ MapEntry<Integer, V> defaultEntry,
+ int fieldNumber) throws IOException {
+ Map<Integer, V> m = field.getMap();
+ if (!out.isSerializationDeterministic()) {
+ serializeMapTo(out, m, defaultEntry, fieldNumber);
+ return;
+ }
+ // Sorting the unboxed keys and then look up the values during serialziation is 2x faster
+ // than sorting map entries with a custom comparator directly.
+ int[] keys = new int[m.size()];
+ int index = 0;
+ for (int k : m.keySet()) {
+ keys[index++] = k;
+ }
+ Arrays.sort(keys);
+ for (int key : keys) {
+ out.writeMessage(fieldNumber,
+ defaultEntry.newBuilderForType()
+ .setKey(key)
+ .setValue(m.get(key))
+ .build());
+ }
+ }
+
+ protected static <V> void serializeLongMapTo(
+ CodedOutputStream out,
+ MapField<Long, V> field,
+ MapEntry<Long, V> defaultEntry,
+ int fieldNumber)
+ throws IOException {
+ Map<Long, V> m = field.getMap();
+ if (!out.isSerializationDeterministic()) {
+ serializeMapTo(out, m, defaultEntry, fieldNumber);
+ return;
+ }
+
+ long[] keys = new long[m.size()];
+ int index = 0;
+ for (long k : m.keySet()) {
+ keys[index++] = k;
+ }
+ Arrays.sort(keys);
+ for (long key : keys) {
+ out.writeMessage(fieldNumber,
+ defaultEntry.newBuilderForType()
+ .setKey(key)
+ .setValue(m.get(key))
+ .build());
+ }
+ }
+
+ protected static <V> void serializeStringMapTo(
+ CodedOutputStream out,
+ MapField<String, V> field,
+ MapEntry<String, V> defaultEntry,
+ int fieldNumber)
+ throws IOException {
+ Map<String, V> m = field.getMap();
+ if (!out.isSerializationDeterministic()) {
+ serializeMapTo(out, m, defaultEntry, fieldNumber);
+ return;
+ }
+
+ // Sorting the String keys and then look up the values during serialziation is 25% faster than
+ // sorting map entries with a custom comparator directly.
+ String[] keys = new String[m.size()];
+ keys = m.keySet().toArray(keys);
+ Arrays.sort(keys);
+ for (String key : keys) {
+ out.writeMessage(fieldNumber,
+ defaultEntry.newBuilderForType()
+ .setKey(key)
+ .setValue(m.get(key))
+ .build());
+ }
+ }
+
+ protected static <V> void serializeBooleanMapTo(
+ CodedOutputStream out,
+ MapField<Boolean, V> field,
+ MapEntry<Boolean, V> defaultEntry,
+ int fieldNumber)
+ throws IOException {
+ Map<Boolean, V> m = field.getMap();
+ if (!out.isSerializationDeterministic()) {
+ serializeMapTo(out, m, defaultEntry, fieldNumber);
+ return;
+ }
+ maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, false);
+ maybeSerializeBooleanEntryTo(out, m, defaultEntry, fieldNumber, true);
+ }
+
+ private static <V> void maybeSerializeBooleanEntryTo(
+ CodedOutputStream out,
+ Map<Boolean, V> m,
+ MapEntry<Boolean, V> defaultEntry,
+ int fieldNumber,
+ boolean key)
+ throws IOException {
+ if (m.containsKey(key)) {
+ out.writeMessage(fieldNumber,
+ defaultEntry.newBuilderForType()
+ .setKey(key)
+ .setValue(m.get(key))
+ .build());
+ }
+ }
+
+ /** Serialize the map using the iteration order. */
+ private static <K, V> void serializeMapTo(
+ CodedOutputStream out,
+ Map<K, V> m,
+ MapEntry<K, V> defaultEntry,
+ int fieldNumber)
+ throws IOException {
+ for (Map.Entry<K, V> entry : m.entrySet()) {
+ out.writeMessage(fieldNumber,
+ defaultEntry.newBuilderForType()
+ .setKey(entry.getKey())
+ .setValue(entry.getValue())
+ .build());
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/IntArrayList.java
new file mode 100644
index 0000000000..2f526e3fd8
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -0,0 +1,272 @@
+// 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 com.google.protobuf.Internal.IntList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link IntList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class IntArrayList
+ extends AbstractProtobufList<Integer>
+ implements IntList, RandomAccess {
+
+ private static final IntArrayList EMPTY_LIST = new IntArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static IntArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private int[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code IntArrayList} with default capacity.
+ */
+ IntArrayList() {
+ this(new int[DEFAULT_CAPACITY], 0);
+ }
+
+ /**
+ * Constructs a new mutable {@code IntArrayList}
+ * containing the same elements as {@code other}.
+ */
+ private IntArrayList(int[] other, int size) {
+ array = other;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof IntArrayList)) {
+ return super.equals(o);
+ }
+ IntArrayList other = (IntArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final int[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + array[i];
+ }
+ return result;
+ }
+
+ @Override
+ public IntList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new IntArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
+ @Override
+ public Integer get(int index) {
+ return getInt(index);
+ }
+
+ @Override
+ public int getInt(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Integer set(int index, Integer element) {
+ return setInt(index, element);
+ }
+
+ @Override
+ public int setInt(int index, int element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ int previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Integer element) {
+ addInt(index, element);
+ }
+
+ /**
+ * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addInt(int element) {
+ addInt(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element.
+ */
+ private void addInt(int index, int element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ int[] newArray = new int[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Integer> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another IntArrayList to avoid boxing elements.
+ if (!(collection instanceof IntArrayList)) {
+ return super.addAll(collection);
+ }
+
+ IntArrayList list = (IntArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Integer remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ int value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Internal.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Internal.java
new file mode 100644
index 0000000000..c234559ce3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -0,0 +1,751 @@
+// 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.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.AbstractList;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.RandomAccess;
+import java.util.Set;
+
+/**
+ * The classes contained within are used internally by the Protocol Buffer
+ * library and generated message implementations. They are public only because
+ * those generated messages do not reside in the {@code protobuf} package.
+ * Others should not use this class directly.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public final class Internal {
+
+ private Internal() {}
+
+ static final Charset UTF_8 = Charset.forName("UTF-8");
+ static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+ /**
+ * Throws an appropriate {@link NullPointerException} if the given objects is {@code null}.
+ */
+ static <T> T checkNotNull(T obj, String message) {
+ if (obj == null) {
+ throw new NullPointerException(message);
+ }
+ return obj;
+ }
+
+ /**
+ * Helper called by generated code to construct default values for string
+ * fields.
+ * <p>
+ * The protocol compiler does not actually contain a UTF-8 decoder -- it
+ * just pushes UTF-8-encoded text around without touching it. The one place
+ * where this presents a problem is when generating Java string literals.
+ * Unicode characters in the string literal would normally need to be encoded
+ * using a Unicode escape sequence, which would require decoding them.
+ * To get around this, protoc instead embeds the UTF-8 bytes into the
+ * generated code and leaves it to the runtime library to decode them.
+ * <p>
+ * It gets worse, though. If protoc just generated a byte array, like:
+ * new byte[] {0x12, 0x34, 0x56, 0x78}
+ * Java actually generates *code* which allocates an array and then fills
+ * in each value. This is much less efficient than just embedding the bytes
+ * directly into the bytecode. To get around this, we need another
+ * work-around. String literals are embedded directly, so protoc actually
+ * generates a string literal corresponding to the bytes. The easiest way
+ * to do this is to use the ISO-8859-1 character set, which corresponds to
+ * the first 256 characters of the Unicode range. Protoc can then use
+ * good old CEscape to generate the string.
+ * <p>
+ * So we have a string literal which represents a set of bytes which
+ * represents another string. This function -- stringDefaultValue --
+ * converts from the generated string to the string we actually want. The
+ * generated code calls this automatically.
+ */
+ public static String stringDefaultValue(String bytes) {
+ return new String(bytes.getBytes(ISO_8859_1), UTF_8);
+ }
+
+ /**
+ * Helper called by generated code to construct default values for bytes
+ * fields.
+ * <p>
+ * This is a lot like {@link #stringDefaultValue}, but for bytes fields.
+ * In this case we only need the second of the two hacks -- allowing us to
+ * embed raw bytes as a string literal with ISO-8859-1 encoding.
+ */
+ public static ByteString bytesDefaultValue(String bytes) {
+ return ByteString.copyFrom(bytes.getBytes(ISO_8859_1));
+ }
+ /**
+ * Helper called by generated code to construct default values for bytes
+ * fields.
+ * <p>
+ * This is like {@link #bytesDefaultValue}, but returns a byte array.
+ */
+ public static byte[] byteArrayDefaultValue(String bytes) {
+ return bytes.getBytes(ISO_8859_1);
+ }
+
+ /**
+ * Helper called by generated code to construct default values for bytes
+ * fields.
+ * <p>
+ * This is like {@link #bytesDefaultValue}, but returns a ByteBuffer.
+ */
+ public static ByteBuffer byteBufferDefaultValue(String bytes) {
+ return ByteBuffer.wrap(byteArrayDefaultValue(bytes));
+ }
+
+ /**
+ * Create a new ByteBuffer and copy all the content of {@code source}
+ * ByteBuffer to the new ByteBuffer. The new ByteBuffer's limit and
+ * capacity will be source.capacity(), and its position will be 0.
+ * Note that the state of {@code source} ByteBuffer won't be changed.
+ */
+ public static ByteBuffer copyByteBuffer(ByteBuffer source) {
+ // Make a duplicate of the source ByteBuffer and read data from the
+ // duplicate. This is to avoid affecting the source ByteBuffer's state.
+ ByteBuffer temp = source.duplicate();
+ // We want to copy all the data in the source ByteBuffer, not just the
+ // remaining bytes.
+ temp.clear();
+ ByteBuffer result = ByteBuffer.allocate(temp.capacity());
+ result.put(temp);
+ result.clear();
+ return result;
+ }
+
+ /**
+ * Helper called by generated code to determine if a byte array is a valid
+ * UTF-8 encoded string such that the original bytes can be converted to
+ * a String object and then back to a byte array round tripping the bytes
+ * without loss. More precisely, returns {@code true} whenever:
+ * <pre> {@code
+ * Arrays.equals(byteString.toByteArray(),
+ * new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
+ * }</pre>
+ *
+ * <p>This method rejects "overlong" byte sequences, as well as
+ * 3-byte sequences that would map to a surrogate character, in
+ * accordance with the restricted definition of UTF-8 introduced in
+ * Unicode 3.1. Note that the UTF-8 decoder included in Oracle's
+ * JDK has been modified to also reject "overlong" byte sequences,
+ * but currently (2011) still accepts 3-byte surrogate character
+ * byte sequences.
+ *
+ * <p>See the Unicode Standard,<br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>As of 2011-02, this method simply returns the result of {@link
+ * ByteString#isValidUtf8()}. Calling that method directly is preferred.
+ *
+ * @param byteString the string to check
+ * @return whether the byte array is round trippable
+ */
+ public static boolean isValidUtf8(ByteString byteString) {
+ return byteString.isValidUtf8();
+ }
+
+ /**
+ * Like {@link #isValidUtf8(ByteString)} but for byte arrays.
+ */
+ public static boolean isValidUtf8(byte[] byteArray) {
+ return Utf8.isValidUtf8(byteArray);
+ }
+
+ /**
+ * Helper method to get the UTF-8 bytes of a string.
+ */
+ public static byte[] toByteArray(String value) {
+ return value.getBytes(UTF_8);
+ }
+
+ /**
+ * Helper method to convert a byte array to a string using UTF-8 encoding.
+ */
+ public static String toStringUtf8(byte[] bytes) {
+ return new String(bytes, UTF_8);
+ }
+
+ /**
+ * Interface for an enum value or value descriptor, to be used in FieldSet.
+ * The lite library stores enum values directly in FieldSets but the full
+ * library stores EnumValueDescriptors in order to better support reflection.
+ */
+ public interface EnumLite {
+ int getNumber();
+ }
+
+ /**
+ * Interface for an object which maps integers to {@link EnumLite}s.
+ * {@link Descriptors.EnumDescriptor} implements this interface by mapping
+ * numbers to {@link Descriptors.EnumValueDescriptor}s. Additionally,
+ * every generated enum type has a static method internalGetValueMap() which
+ * returns an implementation of this type that maps numbers to enum values.
+ */
+ public interface EnumLiteMap<T extends EnumLite> {
+ T findValueByNumber(int number);
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for longs.
+ * @see Long#hashCode()
+ */
+ public static int hashLong(long n) {
+ return (int) (n ^ (n >>> 32));
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for
+ * booleans.
+ * @see Boolean#hashCode()
+ */
+ public static int hashBoolean(boolean b) {
+ return b ? 1231 : 1237;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for enums.
+ * <p>
+ * This is needed because {@link java.lang.Enum#hashCode()} is final, but we
+ * need to use the field number as the hash code to ensure compatibility
+ * between statically and dynamically generated enum objects.
+ */
+ public static int hashEnum(EnumLite e) {
+ return e.getNumber();
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for
+ * enum lists.
+ */
+ public static int hashEnumList(List<? extends EnumLite> list) {
+ int hash = 1;
+ for (EnumLite e : list) {
+ hash = 31 * hash + hashEnum(e);
+ }
+ return hash;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#equals(Object)} for bytes field.
+ */
+ public static boolean equals(List<byte[]> a, List<byte[]> b) {
+ if (a.size() != b.size()) return false;
+ for (int i = 0; i < a.size(); ++i) {
+ if (!Arrays.equals(a.get(i), b.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for bytes field.
+ */
+ public static int hashCode(List<byte[]> list) {
+ int hash = 1;
+ for (byte[] bytes : list) {
+ hash = 31 * hash + hashCode(bytes);
+ }
+ return hash;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for bytes field.
+ */
+ public static int hashCode(byte[] bytes) {
+ // 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.
+ 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.
+ */
+ public static boolean equalsByteBuffer(ByteBuffer a, ByteBuffer b) {
+ if (a.capacity() != b.capacity()) {
+ return false;
+ }
+ // ByteBuffer.equals() will only compare the remaining bytes, but we want to
+ // compare all the content.
+ return a.duplicate().clear().equals(b.duplicate().clear());
+ }
+
+ /**
+ * Helper method for implementing {@link Message#equals(Object)} for bytes
+ * field.
+ */
+ public static boolean equalsByteBuffer(
+ List<ByteBuffer> a, List<ByteBuffer> b) {
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (int i = 0; i < a.size(); ++i) {
+ if (!equalsByteBuffer(a.get(i), b.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for bytes
+ * field.
+ */
+ public static int hashCodeByteBuffer(List<ByteBuffer> list) {
+ int hash = 1;
+ for (ByteBuffer bytes : list) {
+ hash = 31 * hash + hashCodeByteBuffer(bytes);
+ }
+ return hash;
+ }
+
+ private static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ /**
+ * Helper method for implementing {@link Message#hashCode()} for bytes
+ * field.
+ */
+ public static int hashCodeByteBuffer(ByteBuffer bytes) {
+ if (bytes.hasArray()) {
+ // Fast path.
+ 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
+ // hash value.
+ final int bufferSize = bytes.capacity() > DEFAULT_BUFFER_SIZE
+ ? DEFAULT_BUFFER_SIZE : bytes.capacity();
+ final byte[] buffer = new byte[bufferSize];
+ final ByteBuffer duplicated = bytes.duplicate();
+ duplicated.clear();
+ int h = bytes.capacity();
+ while (duplicated.remaining() > 0) {
+ final int length = duplicated.remaining() <= bufferSize ?
+ duplicated.remaining() : bufferSize;
+ duplicated.get(buffer, 0, length);
+ h = partialHash(h, buffer, 0, length);
+ }
+ return h == 0 ? 1 : h;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T extends MessageLite> T getDefaultInstance(Class<T> clazz) {
+ try {
+ Method method = clazz.getMethod("getDefaultInstance");
+ return (T) method.invoke(method);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failed to get default instance for " + clazz, e);
+ }
+ }
+
+ /**
+ * An empty byte array constant used in generated code.
+ */
+ public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+ /**
+ * An empty byte array constant used in generated code.
+ */
+ public static final ByteBuffer EMPTY_BYTE_BUFFER =
+ ByteBuffer.wrap(EMPTY_BYTE_ARRAY);
+
+ /** An empty coded input stream constant used in generated code. */
+ 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>}.
+ *
+ * Protobuf internal. Used in protobuf generated code only.
+ */
+ public static class ListAdapter<F, T> extends AbstractList<T> {
+ /**
+ * Convert individual elements of the List from F to T.
+ */
+ public interface Converter<F, T> {
+ T convert(F from);
+ }
+
+ private final List<F> fromList;
+ private final Converter<F, T> converter;
+
+ public ListAdapter(List<F> fromList, Converter<F, T> converter) {
+ this.fromList = fromList;
+ this.converter = converter;
+ }
+
+ @Override
+ public T get(int index) {
+ return converter.convert(fromList.get(index));
+ }
+
+ @Override
+ public int size() {
+ return fromList.size();
+ }
+ }
+
+ /**
+ * Wrap around a {@code Map<K, RealValue>} and provide a {@code Map<K, V>}
+ * interface.
+ */
+ public static class MapAdapter<K, V, RealValue> extends AbstractMap<K, V> {
+ /**
+ * An interface used to convert between two types.
+ */
+ public interface Converter<A, B> {
+ B doForward(A object);
+ A doBackward(B object);
+ }
+
+ public static <T extends EnumLite> Converter<Integer, T> newEnumConverter(
+ final EnumLiteMap<T> enumMap, final T unrecognizedValue) {
+ return new Converter<Integer, T>() {
+ @Override
+ public T doForward(Integer value) {
+ T result = enumMap.findValueByNumber(value);
+ return result == null ? unrecognizedValue : result;
+ }
+
+ @Override
+ public Integer doBackward(T value) {
+ return value.getNumber();
+ }
+ };
+ }
+
+ private final Map<K, RealValue> realMap;
+ private final Converter<RealValue, V> valueConverter;
+
+ public MapAdapter(Map<K, RealValue> realMap,
+ Converter<RealValue, V> valueConverter) {
+ this.realMap = realMap;
+ this.valueConverter = valueConverter;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V get(Object key) {
+ RealValue result = realMap.get(key);
+ if (result == null) {
+ return null;
+ }
+ return valueConverter.doForward(result);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ RealValue oldValue = realMap.put(key, valueConverter.doBackward(value));
+ if (oldValue == null) {
+ return null;
+ }
+ return valueConverter.doForward(oldValue);
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ return new SetAdapter(realMap.entrySet());
+ }
+
+ private class SetAdapter extends AbstractSet<Map.Entry<K, V>> {
+ private final Set<Map.Entry<K, RealValue>> realSet;
+ public SetAdapter(Set<Map.Entry<K, RealValue>> realSet) {
+ this.realSet = realSet;
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<K, V>> iterator() {
+ return new IteratorAdapter(realSet.iterator());
+ }
+
+ @Override
+ public int size() {
+ return realSet.size();
+ }
+ }
+
+ private class IteratorAdapter implements Iterator<Map.Entry<K, V>> {
+ private final Iterator<Map.Entry<K, RealValue>> realIterator;
+
+ public IteratorAdapter(
+ Iterator<Map.Entry<K, RealValue>> realIterator) {
+ this.realIterator = realIterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return realIterator.hasNext();
+ }
+
+ @Override
+ public java.util.Map.Entry<K, V> next() {
+ return new EntryAdapter(realIterator.next());
+ }
+
+ @Override
+ public void remove() {
+ realIterator.remove();
+ }
+ }
+
+ private class EntryAdapter implements Map.Entry<K, V> {
+ private final Map.Entry<K, RealValue> realEntry;
+
+ public EntryAdapter(Map.Entry<K, RealValue> realEntry) {
+ this.realEntry = realEntry;
+ }
+
+ @Override
+ public K getKey() {
+ return realEntry.getKey();
+ }
+
+ @Override
+ public V getValue() {
+ return valueConverter.doForward(realEntry.getValue());
+ }
+
+ @Override
+ public V setValue(V value) {
+ RealValue oldValue = realEntry.setValue(
+ valueConverter.doBackward(value));
+ if (oldValue == null) {
+ return null;
+ }
+ return valueConverter.doForward(oldValue);
+ }
+ }
+ }
+
+ /**
+ * Extends {@link List} to add the capability to make the list immutable and inspect if it is
+ * modifiable.
+ * <p>
+ * All implementations must support efficient random access.
+ */
+ public static interface ProtobufList<E> extends List<E>, RandomAccess {
+
+ /**
+ * Makes this list immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ void makeImmutable();
+
+ /**
+ * Returns whether this list can be modified via the publicly accessible {@link List} methods.
+ */
+ boolean isModifiable();
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ ProtobufList<E> mutableCopyWithCapacity(int capacity);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Integers if
+ * possible. Does not support null elements.
+ */
+ public static interface IntList extends ProtobufList<Integer> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ int getInt(int index);
+
+ /**
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ */
+ void addInt(int element);
+
+ /**
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ */
+ int setInt(int index, int element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ IntList mutableCopyWithCapacity(int capacity);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Booleans if
+ * possible. Does not support null elements.
+ */
+ public static interface BooleanList extends ProtobufList<Boolean> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ boolean getBoolean(int index);
+
+ /**
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ */
+ void addBoolean(boolean element);
+
+ /**
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ */
+ boolean setBoolean(int index, boolean element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ BooleanList mutableCopyWithCapacity(int capacity);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Longs if
+ * possible. Does not support null elements.
+ */
+ public static interface LongList extends ProtobufList<Long> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ long getLong(int index);
+
+ /**
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ */
+ void addLong(long element);
+
+ /**
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ */
+ long setLong(int index, long element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ LongList mutableCopyWithCapacity(int capacity);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Doubles if
+ * possible. Does not support null elements.
+ */
+ public static interface DoubleList extends ProtobufList<Double> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ double getDouble(int index);
+
+ /**
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ */
+ void addDouble(double element);
+
+ /**
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ */
+ double setDouble(int index, double element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ DoubleList mutableCopyWithCapacity(int capacity);
+ }
+
+ /**
+ * A {@link java.util.List} implementation that avoids boxing the elements into Floats if
+ * possible. Does not support null elements.
+ */
+ public static interface FloatList extends ProtobufList<Float> {
+
+ /**
+ * Like {@link #get(int)} but more efficient in that it doesn't box the returned value.
+ */
+ float getFloat(int index);
+
+ /**
+ * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ */
+ void addFloat(float element);
+
+ /**
+ * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ */
+ float setFloat(int index, float element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ FloatList mutableCopyWithCapacity(int capacity);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
new file mode 100644
index 0000000000..55e33d21d0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -0,0 +1,146 @@
+// 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;
+
+/**
+ * Thrown when a protocol message being parsed is invalid in some way,
+ * e.g. it contains a malformed varint or a negative byte length.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class InvalidProtocolBufferException extends IOException {
+ private static final long serialVersionUID = -1616151763072450476L;
+ private MessageLite unfinishedMessage = null;
+
+ public InvalidProtocolBufferException(final String description) {
+ 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.
+ *
+ * @return this
+ */
+ public InvalidProtocolBufferException setUnfinishedMessage(
+ MessageLite unfinishedMessage) {
+ this.unfinishedMessage = unfinishedMessage;
+ return this;
+ }
+
+ /**
+ * Returns the unfinished message attached to the exception, or null if
+ * no message is attached.
+ */
+ public MessageLite getUnfinishedMessage() {
+ 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 " +
+ "in the middle of a field. This could mean either that the " +
+ "input has been truncated or that an embedded message " +
+ "misreported its own length.");
+ }
+
+ static InvalidProtocolBufferException negativeSize() {
+ return new InvalidProtocolBufferException(
+ "CodedInputStream encountered an embedded string or message " +
+ "which claimed to have negative size.");
+ }
+
+ static InvalidProtocolBufferException malformedVarint() {
+ return new InvalidProtocolBufferException(
+ "CodedInputStream encountered a malformed varint.");
+ }
+
+ static InvalidProtocolBufferException invalidTag() {
+ return new InvalidProtocolBufferException(
+ "Protocol message contained an invalid tag (zero).");
+ }
+
+ static InvalidProtocolBufferException invalidEndTag() {
+ return new InvalidProtocolBufferException(
+ "Protocol message end-group tag did not match expected tag.");
+ }
+
+ static InvalidWireTypeException invalidWireType() {
+ return new InvalidWireTypeException(
+ "Protocol message tag had invalid wire type.");
+ }
+
+ /**
+ * Exception indicating that and unexpected wire type was encountered for a field.
+ */
+ @ExperimentalApi
+ public static class InvalidWireTypeException extends InvalidProtocolBufferException {
+ private static final long serialVersionUID = 3283890091615336259L;
+
+ public InvalidWireTypeException(String description) {
+ super(description);
+ }
+ }
+
+ static InvalidProtocolBufferException recursionLimitExceeded() {
+ return new InvalidProtocolBufferException(
+ "Protocol message had too many levels of nesting. May be malicious. " +
+ "Use CodedInputStream.setRecursionLimit() to increase the depth limit.");
+ }
+
+ static InvalidProtocolBufferException sizeLimitExceeded() {
+ return new InvalidProtocolBufferException(
+ "Protocol message was too large. May be malicious. " +
+ "Use CodedInputStream.setSizeLimit() to increase the size limit.");
+ }
+
+ static InvalidProtocolBufferException parseFailure() {
+ return new InvalidProtocolBufferException("Failed to parse the message.");
+ }
+
+ static InvalidProtocolBufferException invalidUtf8() {
+ return new InvalidProtocolBufferException("Protocol message had invalid UTF-8.");
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyField.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyField.java
new file mode 100644
index 0000000000..98e13ca199
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyField.java
@@ -0,0 +1,154 @@
+// 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.util.Iterator;
+import java.util.Map.Entry;
+
+/**
+ * LazyField encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parse it on-demand.
+ *
+ * Most of key methods are implemented in {@link LazyFieldLite} but this class
+ * can contain default instance of the message to provide {@code hashCode()},
+ * {@code euqals()} and {@code toString()}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyField extends LazyFieldLite {
+
+ /**
+ * Carry a message's default instance which is used by {@code hashCode()}, {@code euqals()} and
+ * {@code toString()}.
+ */
+ private final MessageLite defaultInstance;
+
+ public LazyField(MessageLite defaultInstance,
+ ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ super(extensionRegistry, bytes);
+
+ this.defaultInstance = defaultInstance;
+ }
+
+ @Override
+ public boolean containsDefaultInstance() {
+ return super.containsDefaultInstance() || value == defaultInstance;
+ }
+
+ public MessageLite getValue() {
+ return getValue(defaultInstance);
+ }
+
+ @Override
+ public int hashCode() {
+ return getValue().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return getValue().equals(obj);
+ }
+
+ @Override
+ public String toString() {
+ return getValue().toString();
+ }
+
+ // ====================================================
+
+ /**
+ * LazyEntry and LazyIterator are used to encapsulate the LazyField, when
+ * users iterate all fields from FieldSet.
+ */
+ static class LazyEntry<K> implements Entry<K, Object> {
+ private Entry<K, LazyField> entry;
+
+ private LazyEntry(Entry<K, LazyField> entry) {
+ this.entry = entry;
+ }
+
+ @Override
+ public K getKey() {
+ return entry.getKey();
+ }
+
+ @Override
+ public Object getValue() {
+ LazyField field = entry.getValue();
+ if (field == null) {
+ return null;
+ }
+ return field.getValue();
+ }
+
+ public LazyField getField() {
+ return entry.getValue();
+ }
+
+ @Override
+ public Object setValue(Object value) {
+ if (!(value instanceof MessageLite)) {
+ throw new IllegalArgumentException(
+ "LazyField now only used for MessageSet, "
+ + "and the value of MessageSet must be an instance of MessageLite");
+ }
+ return entry.getValue().setValue((MessageLite) value);
+ }
+ }
+
+ static class LazyIterator<K> implements Iterator<Entry<K, Object>> {
+ private Iterator<Entry<K, Object>> iterator;
+
+ public LazyIterator(Iterator<Entry<K, Object>> iterator) {
+ this.iterator = iterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Entry<K, Object> next() {
+ Entry<K, ?> entry = iterator.next();
+ if (entry.getValue() instanceof LazyField) {
+ return new LazyEntry<K>((Entry<K, LazyField>) entry);
+ }
+ return (Entry<K, Object>) entry;
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
new file mode 100644
index 0000000000..4b0ba0fd6b
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -0,0 +1,437 @@
+// 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;
+
+/**
+ * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores
+ * the message in a ByteString initially and then parses it on-demand.
+ *
+ * LazyFieldLite is thread-compatible: concurrent reads are safe once the proto that this
+ * LazyFieldLite is a part of is no longer being mutated by its Builder. However, explicit
+ * synchronization is needed under read/write situations.
+ *
+ * When a LazyFieldLite is used in the context of a MessageLite object, its behavior is considered
+ * to be immutable and none of the setter methods in its API are expected to be invoked. All of the
+ * getters are expected to be thread-safe. When used in the context of a MessageLite.Builder,
+ * setters can be invoked, but there is no guarantee of thread safety.
+ *
+ * TODO(yatin,dweis): Consider splitting this class's functionality and put the mutable methods
+ * into a separate builder class to allow us to give stronger compile-time guarantees.
+ *
+ * This class is internal implementation detail of the protobuf library, so you don't need to use it
+ * directly.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldLite {
+ private static final ExtensionRegistryLite EMPTY_REGISTRY =
+ ExtensionRegistryLite.getEmptyRegistry();
+
+ /**
+ * The value associated with the LazyFieldLite object is stored in one or more of the following
+ * three fields (delayedBytes, value, memoizedBytes). They should together be interpreted as
+ * follows.
+ * 1) delayedBytes can be non-null, while value and memoizedBytes is null. The object will be in
+ * this state while the value for the object has not yet been parsed.
+ * 2) Both delayedBytes and value are non-null. The object transitions to this state as soon as
+ * some caller needs to access the value (by invoking getValue()).
+ * 3) memoizedBytes is merely an optimization for calls to LazyFieldLite.toByteString() to avoid
+ * recomputing the ByteString representation on each call. Instead, when the value is parsed
+ * from delayedBytes, we will also assign the contents of delayedBytes to memoizedBytes (since
+ * that is the ByteString representation of value).
+ * 4) Finally, if the LazyFieldLite was created directly with a parsed MessageLite value, then
+ * delayedBytes will be null, and memoizedBytes will be initialized only upon the first call to
+ * LazyFieldLite.toByteString().
+ *
+ * Given the above conditions, any caller that needs a serialized representation of this object
+ * must first check if the memoizedBytes or delayedBytes ByteString is non-null and use it
+ * directly; if both of those are null, it can look at the parsed value field. Similarly, any
+ * caller that needs a parsed value must first check if the value field is already non-null, if
+ * not it must parse the value from delayedBytes.
+ */
+
+ /**
+ * A delayed-parsed version of the contents of this field. When this field is non-null, then the
+ * "value" field is allowed to be null until the time that the value needs to be read.
+ *
+ * When delayedBytes is non-null then {@code extensionRegistry} is required to also be non-null.
+ * {@code value} and {@code memoizedBytes} will be initialized lazily.
+ */
+ private ByteString delayedBytes;
+
+ /**
+ * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It
+ * is only guaranteed to be non-null if this message was initialized using bytes and an
+ * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has
+ * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}.
+ */
+ private ExtensionRegistryLite extensionRegistry;
+
+ /**
+ * The parsed value. When this is null and a caller needs access to the MessageLite value, then
+ * {@code delayedBytes} will be parsed lazily at that time.
+ */
+ protected volatile MessageLite value;
+
+ /**
+ * The memoized bytes for {@code value}. This is an optimization for the toByteString() method to
+ * not have to recompute its return-value on each invocation.
+ * TODO(yatin): Figure out whether this optimization is actually necessary.
+ */
+ private volatile ByteString memoizedBytes;
+
+ /**
+ * Constructs a LazyFieldLite with bytes that will be parsed lazily.
+ */
+ public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ checkArguments(extensionRegistry, bytes);
+ this.extensionRegistry = extensionRegistry;
+ this.delayedBytes = bytes;
+ }
+
+ /**
+ * Constructs a LazyFieldLite with no contents, and no ability to parse extensions.
+ */
+ public LazyFieldLite() {
+ }
+
+ /**
+ * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse
+ * the extensions in the value as it has no ExtensionRegistry.
+ */
+ public static LazyFieldLite fromValue(MessageLite value) {
+ LazyFieldLite lf = new LazyFieldLite();
+ lf.setValue(value);
+ return lf;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof LazyFieldLite)) {
+ return false;
+ }
+
+ LazyFieldLite other = (LazyFieldLite) o;
+
+ // Lazy fields do not work well with equals... If both are delayedBytes, we do not have a
+ // mechanism to deserialize them so we rely on bytes equality. Otherwise we coerce into an
+ // actual message (if necessary) and call equals on the message itself. This implies that two
+ // messages can by unequal but then be turned equal simply be invoking a getter on a lazy field.
+ MessageLite value1 = value;
+ MessageLite value2 = other.value;
+ if (value1 == null && value2 == null) {
+ return toByteString().equals(other.toByteString());
+ } else if (value1 != null && value2 != null) {
+ return value1.equals(value2);
+ } else if (value1 != null) {
+ return value1.equals(other.getValue(value1.getDefaultInstanceForType()));
+ } else {
+ return getValue(value2.getDefaultInstanceForType()).equals(value2);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ // We can't provide a memoizable hash code for lazy fields. The byte strings may have different
+ // hash codes but evaluate to equivalent messages. And we have no facility for constructing
+ // a message here if we were not already holding a value.
+ return 1;
+ }
+
+ /**
+ * Determines whether this LazyFieldLite instance represents the default instance of this type.
+ */
+ public boolean containsDefaultInstance() {
+ return memoizedBytes == ByteString.EMPTY
+ || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY);
+ }
+
+ /**
+ * Clears the value state of this instance.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void clear() {
+ // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another
+ // value, but there is no guarantee that it will contain all extensions that were directly set
+ // on the values that need to be merged.
+ delayedBytes = null;
+ value = null;
+ memoizedBytes = null;
+ }
+
+ /**
+ * Overrides the contents of this LazyField.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void set(LazyFieldLite other) {
+ this.delayedBytes = other.delayedBytes;
+ this.value = other.value;
+ this.memoizedBytes = other.memoizedBytes;
+ // If the other LazyFieldLite was created by directly setting the value rather than first by
+ // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing
+ // extensionRegistry, which has no guarantees that it has all the extensions that will be
+ // directly set on the value.
+ if (other.extensionRegistry != null) {
+ this.extensionRegistry = other.extensionRegistry;
+ }
+ }
+
+ /**
+ * Returns message instance. It may do some thread-safe delayed parsing of bytes.
+ *
+ * @param defaultInstance its message's default instance. It's also used to get parser for the
+ * message type.
+ */
+ public MessageLite getValue(MessageLite defaultInstance) {
+ ensureInitialized(defaultInstance);
+ return value;
+ }
+
+ /**
+ * Sets the value of the instance and returns the old value without delay parsing anything.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public MessageLite setValue(MessageLite value) {
+ MessageLite originalValue = this.value;
+ this.delayedBytes = null;
+ this.memoizedBytes = null;
+ this.value = value;
+ return originalValue;
+ }
+
+ /**
+ * Merges another instance's contents. In some cases may drop some extensions if both fields
+ * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this
+ * field will copy over that {@code ExtensionRegistry}.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void merge(LazyFieldLite other) {
+ if (other.containsDefaultInstance()) {
+ return;
+ }
+
+ if (this.containsDefaultInstance()) {
+ set(other);
+ return;
+ }
+
+ // If the other field has an extension registry but this does not, copy over the other extension
+ // registry.
+ if (this.extensionRegistry == null) {
+ this.extensionRegistry = other.extensionRegistry;
+ }
+
+ // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+ // the (probably rare) case that they have different extension registries there is a chance that
+ // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+ // to outway the benefits of combining the extension registries, which is not normally done for
+ // lite protos anyways.
+ if (this.delayedBytes != null && other.delayedBytes != null) {
+ this.delayedBytes = this.delayedBytes.concat(other.delayedBytes);
+ return;
+ }
+
+ // At least one is parsed and both contain data. We won't drop any extensions here directly, but
+ // in the case that the extension registries are not the same then we might in the future if we
+ // need to serialze and parse a message again.
+ if (this.value == null && other.value != null) {
+ setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry));
+ return;
+ } else if (this.value != null && other.value == null) {
+ setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry));
+ return;
+ }
+
+ // At this point we have two fully parsed messages.
+ setValue(this.value.toBuilder().mergeFrom(other.value).build());
+ }
+
+ /**
+ * Merges another instance's contents from a stream.
+ *
+ * <p>LazyField is not thread-safe for write access. Synchronizations are needed
+ * under read/write situations.
+ */
+ public void mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (this.containsDefaultInstance()) {
+ setByteString(input.readBytes(), extensionRegistry);
+ return;
+ }
+
+ // If the other field has an extension registry but this does not, copy over the other extension
+ // registry.
+ if (this.extensionRegistry == null) {
+ this.extensionRegistry = extensionRegistry;
+ }
+
+ // In the case that both of them are not parsed we simply concatenate the bytes to save time. In
+ // the (probably rare) case that they have different extension registries there is a chance that
+ // some of the extensions may be dropped, but the tradeoff of making this operation fast seems
+ // to outway the benefits of combining the extension registries, which is not normally done for
+ // lite protos anyways.
+ if (this.delayedBytes != null) {
+ setByteString(this.delayedBytes.concat(input.readBytes()), this.extensionRegistry);
+ return;
+ }
+
+ // We are parsed and both contain data. We won't drop any extensions here directly, but in the
+ // case that the extension registries are not the same then we might in the future if we
+ // need to serialize and parse a message again.
+ try {
+ setValue(value.toBuilder().mergeFrom(input, extensionRegistry).build());
+ } catch (InvalidProtocolBufferException e) {
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+ // was invalid.
+ }
+ }
+
+ private static MessageLite mergeValueAndBytes(
+ MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) {
+ try {
+ return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build();
+ } catch (InvalidProtocolBufferException e) {
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto
+ // was invalid.
+ return value;
+ }
+ }
+
+ /**
+ * Sets this field with bytes to delay-parse.
+ */
+ public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
+ checkArguments(extensionRegistry, bytes);
+ this.delayedBytes = bytes;
+ this.extensionRegistry = extensionRegistry;
+ this.value = null;
+ this.memoizedBytes = null;
+ }
+
+ /**
+ * Due to the optional field can be duplicated at the end of serialized
+ * bytes, which will make the serialized size changed after LazyField
+ * parsed. Be careful when using this method.
+ */
+ public int getSerializedSize() {
+ // We *must* return delayed bytes size if it was ever set because the dependent messages may
+ // have memoized serialized size based off of it.
+ if (memoizedBytes != null) {
+ return memoizedBytes.size();
+ } else if (delayedBytes != null) {
+ return delayedBytes.size();
+ } else if (value != null) {
+ return value.getSerializedSize();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns a BytesString for this field in a thread-safe way.
+ */
+ public ByteString toByteString() {
+ if (memoizedBytes != null) {
+ return memoizedBytes;
+ }
+ // We *must* return delayed bytes if it was set because the dependent messages may have
+ // memoized serialized size based off of it.
+ if (delayedBytes != null) {
+ return delayedBytes;
+ }
+ synchronized (this) {
+ if (memoizedBytes != null) {
+ return memoizedBytes;
+ }
+ if (value == null) {
+ memoizedBytes = ByteString.EMPTY;
+ } else {
+ memoizedBytes = value.toByteString();
+ }
+ return memoizedBytes;
+ }
+ }
+
+ /**
+ * Might lazily parse the bytes that were previously passed in. Is thread-safe.
+ */
+ protected void ensureInitialized(MessageLite defaultInstance) {
+ if (value != null) {
+ return;
+ }
+ synchronized (this) {
+ if (value != null) {
+ return;
+ }
+ try {
+ if (delayedBytes != null) {
+ // The extensionRegistry shouldn't be null here since we have delayedBytes.
+ MessageLite parsedValue = defaultInstance.getParserForType()
+ .parseFrom(delayedBytes, extensionRegistry);
+ this.value = parsedValue;
+ this.memoizedBytes = delayedBytes;
+ } else {
+ this.value = defaultInstance;
+ this.memoizedBytes = ByteString.EMPTY;
+ }
+ } catch (InvalidProtocolBufferException e) {
+ // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto
+ // was invalid.
+ this.value = defaultInstance;
+ this.memoizedBytes = ByteString.EMPTY;
+ }
+ }
+ }
+
+
+ private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
+ if (extensionRegistry == null) {
+ throw new NullPointerException("found null ExtensionRegistry");
+ }
+ if (bytes == null) {
+ throw new NullPointerException("found null ByteString");
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
new file mode 100644
index 0000000000..d474c51ef1
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -0,0 +1,423 @@
+// 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.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps an ArrayList. Each
+ * element is one of String, ByteString, or byte[]. It caches the last one
+ * requested which is most likely the one needed next. This minimizes memory
+ * usage while satisfying the most common use cases.
+ * <p>
+ * <strong>Note that this implementation is not synchronized.</strong>
+ * If multiple threads access an <tt>ArrayList</tt> instance concurrently,
+ * and at least one of the threads modifies the list structurally, it
+ * <i>must</i> be synchronized externally. (A structural modification is
+ * any operation that adds or deletes one or more elements, or explicitly
+ * resizes the backing array; merely setting the value of an element is not
+ * a structural modification.) This is typically accomplished by
+ * synchronizing on some object that naturally encapsulates the list.
+ * <p>
+ * If the implementation is accessed via concurrent reads, this is thread safe.
+ * Conversions are done in a thread safe manner. It's possible that the
+ * conversion may happen more than once if two threads attempt to access the
+ * same element and the modifications were not visible to each other, but this
+ * will not result in any corruption of the list or change in behavior other
+ * than performance.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayList extends AbstractProtobufList<String>
+ implements LazyStringList, RandomAccess {
+
+ private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ static LazyStringArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ // For compatibility with older runtimes.
+ public static final LazyStringList EMPTY = EMPTY_LIST;
+
+ private final List<Object> list;
+
+ public LazyStringArrayList() {
+ this(DEFAULT_CAPACITY);
+ }
+
+ public LazyStringArrayList(int intialCapacity) {
+ this(new ArrayList<Object>(intialCapacity));
+ }
+
+ public LazyStringArrayList(LazyStringList from) {
+ list = new ArrayList<Object>(from.size());
+ addAll(from);
+ }
+
+ public LazyStringArrayList(List<String> from) {
+ this(new ArrayList<Object>(from));
+ }
+
+ private LazyStringArrayList(ArrayList<Object> list) {
+ this.list = list;
+ }
+
+ @Override
+ public LazyStringArrayList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size()) {
+ throw new IllegalArgumentException();
+ }
+ ArrayList<Object> newList = new ArrayList<Object>(capacity);
+ newList.addAll(list);
+ return new LazyStringArrayList(newList);
+ }
+
+ @Override
+ public String get(int index) {
+ Object o = list.get(index);
+ if (o instanceof String) {
+ return (String) o;
+ } else if (o instanceof ByteString) {
+ ByteString bs = (ByteString) o;
+ String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ list.set(index, s);
+ }
+ return s;
+ } else {
+ byte[] ba = (byte[]) o;
+ String s = Internal.toStringUtf8(ba);
+ if (Internal.isValidUtf8(ba)) {
+ list.set(index, s);
+ }
+ return s;
+ }
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public String set(int index, String s) {
+ ensureIsMutable();
+ Object o = list.set(index, s);
+ return asString(o);
+ }
+
+ @Override
+ public void add(int index, String element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ private void add(int index, ByteString element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ private void add(int index, byte[] element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends String> c) {
+ // The default implementation of AbstractCollection.addAll(Collection)
+ // delegates to add(Object). This implementation instead delegates to
+ // addAll(int, Collection), which makes a special case for Collections
+ // which are instances of LazyStringList.
+ return addAll(size(), c);
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends String> c) {
+ ensureIsMutable();
+ // When copying from another LazyStringList, directly copy the underlying
+ // elements rather than forcing each element to be decoded to a String.
+ Collection<?> collection = c instanceof LazyStringList
+ ? ((LazyStringList) c).getUnderlyingElements() : c;
+ boolean ret = list.addAll(index, collection);
+ modCount++;
+ return ret;
+ }
+
+ @Override
+ public boolean addAllByteString(Collection<? extends ByteString> values) {
+ ensureIsMutable();
+ boolean ret = list.addAll(values);
+ modCount++;
+ return ret;
+ }
+
+ @Override
+ public boolean addAllByteArray(Collection<byte[]> c) {
+ ensureIsMutable();
+ boolean ret = list.addAll(c);
+ modCount++;
+ return ret;
+ }
+
+ @Override
+ public String remove(int index) {
+ ensureIsMutable();
+ Object o = list.remove(index);
+ modCount++;
+ return asString(o);
+ }
+
+ @Override
+ public void clear() {
+ ensureIsMutable();
+ list.clear();
+ modCount++;
+ }
+
+ @Override
+ public void add(ByteString element) {
+ ensureIsMutable();
+ list.add(element);
+ modCount++;
+ }
+
+ @Override
+ public void add(byte[] element) {
+ ensureIsMutable();
+ list.add(element);
+ modCount++;
+ }
+
+ @Override
+ public Object getRaw(int index) {
+ return list.get(index);
+ }
+
+ @Override
+ public ByteString getByteString(int index) {
+ Object o = list.get(index);
+ ByteString b = asByteString(o);
+ if (b != o) {
+ list.set(index, b);
+ }
+ return b;
+ }
+
+ @Override
+ public byte[] getByteArray(int index) {
+ Object o = list.get(index);
+ byte[] b = asByteArray(o);
+ if (b != o) {
+ list.set(index, b);
+ }
+ return b;
+ }
+
+ @Override
+ public void set(int index, ByteString s) {
+ setAndReturn(index, s);
+ }
+
+ private Object setAndReturn(int index, ByteString s) {
+ ensureIsMutable();
+ return list.set(index, s);
+ }
+
+ @Override
+ public void set(int index, byte[] s) {
+ setAndReturn(index, s);
+ }
+
+ private Object setAndReturn(int index, byte[] s) {
+ ensureIsMutable();
+ return list.set(index, s);
+ }
+
+ private static String asString(Object o) {
+ if (o instanceof String) {
+ return (String) o;
+ } else if (o instanceof ByteString) {
+ return ((ByteString) o).toStringUtf8();
+ } else {
+ return Internal.toStringUtf8((byte[]) o);
+ }
+ }
+
+ private static ByteString asByteString(Object o) {
+ if (o instanceof ByteString) {
+ return (ByteString) o;
+ } else if (o instanceof String) {
+ return ByteString.copyFromUtf8((String) o);
+ } else {
+ return ByteString.copyFrom((byte[]) o);
+ }
+ }
+
+ private static byte[] asByteArray(Object o) {
+ if (o instanceof byte[]) {
+ return (byte[]) o;
+ } else if (o instanceof String) {
+ return Internal.toByteArray((String) o);
+ } else {
+ return ((ByteString) o).toByteArray();
+ }
+ }
+
+ @Override
+ public List<?> getUnderlyingElements() {
+ return Collections.unmodifiableList(list);
+ }
+
+ @Override
+ public void mergeFrom(LazyStringList other) {
+ ensureIsMutable();
+ for (Object o : other.getUnderlyingElements()) {
+ if (o instanceof byte[]) {
+ byte[] b = (byte[]) o;
+ // Byte array's content is mutable so they should be copied rather than
+ // shared when merging from one message to another.
+ list.add(Arrays.copyOf(b, b.length));
+ } else {
+ list.add(o);
+ }
+ }
+ }
+
+ private static class ByteArrayListView extends AbstractList<byte[]>
+ implements RandomAccess {
+ private final LazyStringArrayList list;
+
+ ByteArrayListView(LazyStringArrayList list) {
+ this.list = list;
+ }
+
+ @Override
+ public byte[] get(int index) {
+ return list.getByteArray(index);
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public byte[] set(int index, byte[] s) {
+ Object o = list.setAndReturn(index, s);
+ modCount++;
+ return asByteArray(o);
+ }
+
+ @Override
+ public void add(int index, byte[] s) {
+ list.add(index, s);
+ modCount++;
+ }
+
+ @Override
+ public byte[] remove(int index) {
+ Object o = list.remove(index);
+ modCount++;
+ return asByteArray(o);
+ }
+ }
+
+ @Override
+ public List<byte[]> asByteArrayList() {
+ return new ByteArrayListView(this);
+ }
+
+ private static class ByteStringListView extends AbstractList<ByteString>
+ implements RandomAccess {
+ private final LazyStringArrayList list;
+
+ ByteStringListView(LazyStringArrayList list) {
+ this.list = list;
+ }
+
+ @Override
+ public ByteString get(int index) {
+ return list.getByteString(index);
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public ByteString set(int index, ByteString s) {
+ Object o = list.setAndReturn(index, s);
+ modCount++;
+ return asByteString(o);
+ }
+
+ @Override
+ public void add(int index, ByteString s) {
+ list.add(index, s);
+ modCount++;
+ }
+
+ @Override
+ public ByteString remove(int index) {
+ Object o = list.remove(index);
+ modCount++;
+ return asByteString(o);
+ }
+ }
+
+ @Override
+ public List<ByteString> asByteStringList() {
+ return new ByteStringListView(this);
+ }
+
+ @Override
+ public LazyStringList getUnmodifiableView() {
+ if (isModifiable()) {
+ return new UnmodifiableLazyStringList(this);
+ }
+ return this;
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringList.java
new file mode 100644
index 0000000000..3eeedca1d3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LazyStringList.java
@@ -0,0 +1,174 @@
+// 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.util.Collection;
+import java.util.List;
+
+/**
+ * An interface extending {@code List<String>} that also provides access to the
+ * items of the list as UTF8-encoded ByteString or byte[] objects. This is
+ * used by the protocol buffer implementation to support lazily converting bytes
+ * parsed over the wire to String objects until needed and also increases the
+ * efficiency of serialization if the String was never requested as the
+ * ByteString or byte[] is already cached. The ByteString methods are used in
+ * immutable API only and byte[] methods used in mutable API only for they use
+ * different representations for string/bytes fields.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface LazyStringList extends ProtocolStringList {
+
+ /**
+ * Returns the element at the specified position in this list as a ByteString.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ ByteString getByteString(int index);
+
+ /**
+ * Returns the element at the specified position in this list as an Object
+ * that will either be a String or a ByteString.
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ Object getRaw(int index);
+
+ /**
+ * Returns the element at the specified position in this list as byte[].
+ *
+ * @param index index of the element to return
+ * @return the element at the specified position in this list
+ * @throws IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ byte[] getByteArray(int index);
+
+ /**
+ * Appends the specified element to the end of this list (optional
+ * operation).
+ *
+ * @param element element to be appended to this list
+ * @throws UnsupportedOperationException if the <tt>add</tt> operation
+ * is not supported by this list
+ */
+ void add(ByteString element);
+
+ /**
+ * Appends the specified element to the end of this list (optional
+ * operation).
+ *
+ * @param element element to be appended to this list
+ * @throws UnsupportedOperationException if the <tt>add</tt> operation
+ * is not supported by this list
+ */
+ void add(byte[] element);
+
+ /**
+ * Replaces the element at the specified position in this list with the
+ * specified element (optional operation).
+ *
+ * @param index index of the element to replace
+ * @param element the element to be stored at the specified position
+ * @throws UnsupportedOperationException if the <tt>set</tt> operation
+ * is not supported by this list
+ * IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ void set(int index, ByteString element);
+
+ /**
+ * Replaces the element at the specified position in this list with the
+ * specified element (optional operation).
+ *
+ * @param index index of the element to replace
+ * @param element the element to be stored at the specified position
+ * @throws UnsupportedOperationException if the <tt>set</tt> operation
+ * is not supported by this list
+ * IndexOutOfBoundsException if the index is out of range
+ * ({@code index < 0 || index >= size()})
+ */
+ void set(int index, byte[] element);
+
+ /**
+ * Appends all elements in the specified ByteString collection to the end of
+ * this list.
+ *
+ * @param c collection whose elements are to be added to this list
+ * @return true if this list changed as a result of the call
+ * @throws UnsupportedOperationException if the <tt>addAllByteString</tt>
+ * operation is not supported by this list
+ */
+ boolean addAllByteString(Collection<? extends ByteString> c);
+
+ /**
+ * Appends all elements in the specified byte[] collection to the end of
+ * this list.
+ *
+ * @param c collection whose elements are to be added to this list
+ * @return true if this list changed as a result of the call
+ * @throws UnsupportedOperationException if the <tt>addAllByteArray</tt>
+ * operation is not supported by this list
+ */
+ boolean addAllByteArray(Collection<byte[]> c);
+
+ /**
+ * Returns an unmodifiable List of the underlying elements, each of which is
+ * either a {@code String} or its equivalent UTF-8 encoded {@code ByteString}
+ * or byte[]. It is an error for the caller to modify the returned
+ * List, and attempting to do so will result in an
+ * {@link UnsupportedOperationException}.
+ */
+ List<?> getUnderlyingElements();
+
+ /**
+ * Merges all elements from another LazyStringList into this one. This method
+ * differs from {@link #addAll(Collection)} on that underlying byte arrays are
+ * copied instead of reference shared. Immutable API doesn't need to use this
+ * method as byte[] is not used there at all.
+ */
+ void mergeFrom(LazyStringList other);
+
+ /**
+ * Returns a mutable view of this list. Changes to the view will be made into
+ * the original list. This method is used in mutable API only.
+ */
+ List<byte[]> asByteArrayList();
+
+ /** Returns an unmodifiable view of the list. */
+ LazyStringList getUnmodifiableView();
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LongArrayList.java
new file mode 100644
index 0000000000..5a772e3aa8
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -0,0 +1,272 @@
+// 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 com.google.protobuf.Internal.LongList;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LongList} on top of a primitive array.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+final class LongArrayList
+ extends AbstractProtobufList<Long>
+ implements LongList, RandomAccess {
+
+ private static final LongArrayList EMPTY_LIST = new LongArrayList();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ public static LongArrayList emptyList() {
+ return EMPTY_LIST;
+ }
+
+ /**
+ * The backing store for the list.
+ */
+ private long[] array;
+
+ /**
+ * The size of the list distinct from the length of the array. That is, it is the number of
+ * elements set in the list.
+ */
+ private int size;
+
+ /**
+ * Constructs a new mutable {@code LongArrayList} with default capacity.
+ */
+ LongArrayList() {
+ this(new long[DEFAULT_CAPACITY], 0);
+ }
+
+ /**
+ * Constructs a new mutable {@code LongArrayList}
+ * containing the same elements as {@code other}.
+ */
+ private LongArrayList(long[] other, int size) {
+ array = other;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof LongArrayList)) {
+ return super.equals(o);
+ }
+ LongArrayList other = (LongArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final long[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Internal.hashLong(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public LongList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new LongArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
+ @Override
+ public Long get(int index) {
+ return getLong(index);
+ }
+
+ @Override
+ public long getLong(int index) {
+ ensureIndexInRange(index);
+ return array[index];
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public Long set(int index, Long element) {
+ return setLong(index, element);
+ }
+
+ @Override
+ public long setLong(int index, long element) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ long previousValue = array[index];
+ array[index] = element;
+ return previousValue;
+ }
+
+ @Override
+ public void add(int index, Long element) {
+ addLong(index, element);
+ }
+
+ /**
+ * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
+ */
+ @Override
+ public void addLong(long element) {
+ addLong(size, element);
+ }
+
+ /**
+ * Like {@link #add(int, Long)} but more efficient in that it doesn't box the element.
+ */
+ private void addLong(int index, long element) {
+ ensureIsMutable();
+ if (index < 0 || index > size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+
+ if (size < array.length) {
+ // Shift everything over to make room
+ System.arraycopy(array, index, array, index + 1, size - index);
+ } else {
+ // Resize to 1.5x the size
+ int length = ((size * 3) / 2) + 1;
+ long[] newArray = new long[length];
+
+ // Copy the first part directly
+ System.arraycopy(array, 0, newArray, 0, index);
+
+ // Copy the rest shifted over by one to make room
+ System.arraycopy(array, index, newArray, index + 1, size - index);
+ array = newArray;
+ }
+
+ array[index] = element;
+ size++;
+ modCount++;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends Long> collection) {
+ ensureIsMutable();
+
+ if (collection == null) {
+ throw new NullPointerException();
+ }
+
+ // We specialize when adding another LongArrayList to avoid boxing elements.
+ if (!(collection instanceof LongArrayList)) {
+ return super.addAll(collection);
+ }
+
+ LongArrayList list = (LongArrayList) collection;
+ if (list.size == 0) {
+ return false;
+ }
+
+ int overflow = Integer.MAX_VALUE - size;
+ if (overflow < list.size) {
+ // We can't actually represent a list this large.
+ throw new OutOfMemoryError();
+ }
+
+ int newSize = size + list.size;
+ if (newSize > array.length) {
+ array = Arrays.copyOf(array, newSize);
+ }
+
+ System.arraycopy(list.array, 0, array, size, list.size);
+ size = newSize;
+ modCount++;
+ return true;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ ensureIsMutable();
+ for (int i = 0; i < size; i++) {
+ if (o.equals(array[i])) {
+ System.arraycopy(array, i + 1, array, i, size - i);
+ size--;
+ modCount++;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Long remove(int index) {
+ ensureIsMutable();
+ ensureIndexInRange(index);
+ long value = array[index];
+ System.arraycopy(array, index + 1, array, index, size - index);
+ size--;
+ modCount++;
+ return value;
+ }
+
+ /**
+ * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
+ * {@link IndexOutOfBoundsException} if it is not.
+ *
+ * @param index the index to verify is in range
+ */
+ private void ensureIndexInRange(int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
+ }
+ }
+
+ private String makeOutOfBoundsExceptionMessage(int index) {
+ return "Index:" + index + ", Size:" + size;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
new file mode 100644
index 0000000000..7e8e9aad54
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntry.java
@@ -0,0 +1,451 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Implements MapEntry messages.
+ *
+ * In reflection API, map fields will be treated as repeated message fields and
+ * each map entry is accessed as a message. This MapEntry class is used to
+ * represent these map entry messages in reflection API.
+ *
+ * Protobuf internal. Users shouldn't use this class.
+ */
+public final class MapEntry<K, V> extends AbstractMessage {
+
+ private static final class Metadata<K, V> extends MapEntryLite.Metadata<K, V> {
+
+ public final Descriptor descriptor;
+ public final Parser<MapEntry<K, V>> parser;
+
+ public Metadata(
+ Descriptor descriptor,
+ MapEntry<K, V> defaultInstance,
+ WireFormat.FieldType keyType,
+ WireFormat.FieldType valueType) {
+ super(keyType, defaultInstance.key, valueType, defaultInstance.value);
+ this.descriptor = descriptor;
+ this.parser = new AbstractParser<MapEntry<K, V>>() {
+
+ @Override
+ public MapEntry<K, V> parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ return new MapEntry<K, V>(Metadata.this, input, extensionRegistry);
+ }
+ };
+ }
+ }
+
+ private final K key;
+ private final V value;
+ private final Metadata<K, V> metadata;
+
+ /** Create a default MapEntry instance. */
+ private MapEntry(
+ Descriptor descriptor,
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ this.key = defaultKey;
+ this.value = defaultValue;
+ this.metadata = new Metadata<K, V>(descriptor, this, keyType, valueType);
+ }
+
+ /** Create a MapEntry with the provided key and value. */
+ @SuppressWarnings("unchecked")
+ private MapEntry(Metadata metadata, K key, V value) {
+ this.key = key;
+ this.value = value;
+ this.metadata = metadata;
+ }
+
+ /** Parsing constructor. */
+ private MapEntry(
+ Metadata<K, V> metadata,
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ this.metadata = metadata;
+ Map.Entry<K, V> entry = MapEntryLite.parseEntry(input, metadata, extensionRegistry);
+ this.key = entry.getKey();
+ this.value = entry.getValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this);
+ }
+ }
+
+ /**
+ * Create a default MapEntry instance. A default MapEntry instance should be
+ * created only once for each map entry message type. Generated code should
+ * store the created default instance and use it later to create new MapEntry
+ * messages of the same type.
+ */
+ public static <K, V> MapEntry<K, V> newDefaultInstance(
+ Descriptor descriptor,
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ return new MapEntry<K, V>(
+ descriptor, keyType, defaultKey, valueType, defaultValue);
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ private volatile int cachedSerializedSize = -1;
+
+ @Override
+ public int getSerializedSize() {
+ if (cachedSerializedSize != -1) {
+ return cachedSerializedSize;
+ }
+
+ int size = MapEntryLite.computeSerializedSize(metadata, key, value);
+ cachedSerializedSize = size;
+ return size;
+ }
+
+ @Override
+ public void writeTo(CodedOutputStream output) throws IOException {
+ MapEntryLite.writeTo(output, metadata, key, value);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized(metadata, value);
+ }
+
+ @Override
+ public Parser<MapEntry<K, V>> getParserForType() {
+ return metadata.parser;
+ }
+
+ @Override
+ public Builder<K, V> newBuilderForType() {
+ return new Builder<K, V>(metadata);
+ }
+
+ @Override
+ public Builder<K, V> toBuilder() {
+ return new Builder<K, V>(metadata, key, value);
+ }
+
+ @Override
+ public MapEntry<K, V> getDefaultInstanceForType() {
+ return new MapEntry<K, V>(metadata, metadata.defaultKey, metadata.defaultValue);
+ }
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return metadata.descriptor;
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
+ for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+ if (hasField(field)) {
+ result.put(field, getField(field));
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
+
+ private void checkFieldDescriptor(FieldDescriptor field) {
+ if (field.getContainingType() != metadata.descriptor) {
+ throw new RuntimeException(
+ "Wrong FieldDescriptor \"" + field.getFullName()
+ + "\" used in message \"" + metadata.descriptor.getFullName());
+ }
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ checkFieldDescriptor(field);;
+ // A MapEntry always contains two fields.
+ return true;
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ Object result = field.getNumber() == 1 ? getKey() : getValue();
+ // Convert enums to EnumValueDescriptor.
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ result = field.getEnumType().findValueByNumberCreatingIfUnknown(
+ (java.lang.Integer) result);
+ }
+ return result;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ /**
+ * Builder to create {@link MapEntry} messages.
+ */
+ public static class Builder<K, V>
+ extends AbstractMessage.Builder<Builder<K, V>> {
+ private final Metadata<K, V> metadata;
+ private K key;
+ private V value;
+
+ private Builder(Metadata<K, V> metadata) {
+ this(metadata, metadata.defaultKey, metadata.defaultValue);
+ }
+
+ private Builder(Metadata<K, V> metadata, K key, V value) {
+ this.metadata = metadata;
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public Builder<K, V> setKey(K key) {
+ this.key = key;
+ return this;
+ }
+
+ public Builder<K, V> clearKey() {
+ this.key = metadata.defaultKey;
+ return this;
+ }
+
+ public Builder<K, V> setValue(V value) {
+ this.value = value;
+ return this;
+ }
+
+ public Builder<K, V> clearValue() {
+ this.value = metadata.defaultValue;
+ return this;
+ }
+
+ @Override
+ public MapEntry<K, V> build() {
+ MapEntry<K, V> result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @Override
+ public MapEntry<K, V> buildPartial() {
+ return new MapEntry<K, V>(metadata, key, value);
+ }
+
+ @Override
+ public Descriptor getDescriptorForType() {
+ return metadata.descriptor;
+ }
+
+ private void checkFieldDescriptor(FieldDescriptor field) {
+ if (field.getContainingType() != metadata.descriptor) {
+ throw new RuntimeException(
+ "Wrong FieldDescriptor \"" + field.getFullName()
+ + "\" used in message \"" + metadata.descriptor.getFullName());
+ }
+ }
+
+ @Override
+ public Message.Builder newBuilderForField(FieldDescriptor field) {
+ checkFieldDescriptor(field);;
+ // This method should be called for message fields and in a MapEntry
+ // message only the value field can possibly be a message field.
+ if (field.getNumber() != 2
+ || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ throw new RuntimeException(
+ "\"" + field.getFullName() + "\" is not a message value field.");
+ }
+ return ((Message) value).newBuilderForType();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Builder<K, V> setField(FieldDescriptor field, Object value) {
+ checkFieldDescriptor(field);
+ if (field.getNumber() == 1) {
+ setKey((K) value);
+ } else {
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ value = ((EnumValueDescriptor) value).getNumber();
+ } else if (field.getType() == FieldDescriptor.Type.MESSAGE) {
+ if (value != null && !metadata.defaultValue.getClass().isInstance(value)) {
+ // The value is not the exact right message type. However, if it
+ // is an alternative implementation of the same type -- e.g. a
+ // DynamicMessage -- we should accept it. In this case we can make
+ // a copy of the message.
+ value =
+ ((Message) metadata.defaultValue).toBuilder().mergeFrom((Message) value).build();
+ }
+ }
+ setValue((V) value);
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> clearField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ if (field.getNumber() == 1) {
+ clearKey();
+ } else {
+ clearValue();
+ }
+ return this;
+ }
+
+ @Override
+ public Builder<K, V> setRepeatedField(FieldDescriptor field, int index,
+ Object value) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Builder<K, V> addRepeatedField(FieldDescriptor field, Object value) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Builder<K, V> setUnknownFields(UnknownFieldSet unknownFields) {
+ // Unknown fields are discarded for MapEntry message.
+ return this;
+ }
+
+ @Override
+ public MapEntry<K, V> getDefaultInstanceForType() {
+ return new MapEntry<K, V>(metadata, metadata.defaultKey, metadata.defaultValue);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return MapEntry.isInitialized(metadata, value);
+ }
+
+ @Override
+ public Map<FieldDescriptor, Object> getAllFields() {
+ final TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
+ for (final FieldDescriptor field : metadata.descriptor.getFields()) {
+ if (hasField(field)) {
+ result.put(field, getField(field));
+ }
+ }
+ return Collections.unmodifiableMap(result);
+ }
+
+ @Override
+ public boolean hasField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ return true;
+ }
+
+ @Override
+ public Object getField(FieldDescriptor field) {
+ checkFieldDescriptor(field);
+ Object result = field.getNumber() == 1 ? getKey() : getValue();
+ // Convert enums to EnumValueDescriptor.
+ if (field.getType() == FieldDescriptor.Type.ENUM) {
+ result = field.getEnumType().findValueByNumberCreatingIfUnknown((Integer) result);
+ }
+ return result;
+ }
+
+ @Override
+ public int getRepeatedFieldCount(FieldDescriptor field) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public Object getRepeatedField(FieldDescriptor field, int index) {
+ throw new RuntimeException(
+ "There is no repeated field in a map entry message.");
+ }
+
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Builder<K, V> clone() {
+ return new Builder(metadata, key, value);
+ }
+ }
+
+ private static <V> boolean isInitialized(Metadata metadata, V value) {
+ if (metadata.valueType.getJavaType() == WireFormat.JavaType.MESSAGE) {
+ return ((MessageLite) value).isInitialized();
+ }
+ return true;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntryLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
new file mode 100644
index 0000000000..22aef8f93d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
@@ -0,0 +1,226 @@
+// 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.util.AbstractMap;
+import java.util.Map;
+
+/**
+ * Implements the lite version of map entry messages.
+ *
+ * This class serves as an utility class to help do serialization/parsing of
+ * map entries. It's used in generated code and also in the full version
+ * MapEntry message.
+ *
+ * Protobuf internal. Users shouldn't use.
+ */
+public class MapEntryLite<K, V> {
+
+ static class Metadata<K, V> {
+ public final WireFormat.FieldType keyType;
+ public final K defaultKey;
+ public final WireFormat.FieldType valueType;
+ public final V defaultValue;
+
+ public Metadata(
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ this.keyType = keyType;
+ this.defaultKey = defaultKey;
+ this.valueType = valueType;
+ this.defaultValue = defaultValue;
+ }
+ }
+
+ private static final int KEY_FIELD_NUMBER = 1;
+ private static final int VALUE_FIELD_NUMBER = 2;
+
+ private final Metadata<K, V> metadata;
+ private final K key;
+ private final V value;
+
+ /** Creates a default MapEntryLite message instance. */
+ private MapEntryLite(
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ this.metadata = new Metadata<K, V>(keyType, defaultKey, valueType, defaultValue);
+ this.key = defaultKey;
+ this.value = defaultValue;
+ }
+
+ /** Creates a new MapEntryLite message. */
+ private MapEntryLite(Metadata<K, V> metadata, K key, V value) {
+ this.metadata = metadata;
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() {
+ return key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ /**
+ * Creates a default MapEntryLite message instance.
+ *
+ * This method is used by generated code to create the default instance for
+ * a map entry message. The created default instance should be used to create
+ * new map entry messages of the same type. For each map entry message, only
+ * one default instance should be created.
+ */
+ public static <K, V> MapEntryLite<K, V> newDefaultInstance(
+ WireFormat.FieldType keyType, K defaultKey,
+ WireFormat.FieldType valueType, V defaultValue) {
+ return new MapEntryLite<K, V>(
+ keyType, defaultKey, valueType, defaultValue);
+ }
+
+ static <K, V> void writeTo(CodedOutputStream output, Metadata<K, V> metadata, K key, V value)
+ throws IOException {
+ FieldSet.writeElement(output, metadata.keyType, KEY_FIELD_NUMBER, key);
+ FieldSet.writeElement(output, metadata.valueType, VALUE_FIELD_NUMBER, value);
+ }
+
+ static <K, V> int computeSerializedSize(Metadata<K, V> metadata, K key, V value) {
+ return FieldSet.computeElementSize(metadata.keyType, KEY_FIELD_NUMBER, key)
+ + FieldSet.computeElementSize(metadata.valueType, VALUE_FIELD_NUMBER, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <T> T parseField(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry,
+ WireFormat.FieldType type, T value) throws IOException {
+ switch (type) {
+ case MESSAGE:
+ MessageLite.Builder subBuilder = ((MessageLite) value).toBuilder();
+ input.readMessage(subBuilder, extensionRegistry);
+ return (T) subBuilder.buildPartial();
+ case ENUM:
+ return (T) (java.lang.Integer) input.readEnum();
+ case GROUP:
+ throw new RuntimeException("Groups are not allowed in maps.");
+ default:
+ return (T) FieldSet.readPrimitiveField(input, type, true);
+ }
+ }
+
+ /**
+ * Serializes the provided key and value as though they were wrapped by a {@link MapEntryLite}
+ * to the output stream. This helper method avoids allocation of a {@link MapEntryLite}
+ * built with a key and value and is called from generated code directly.
+ */
+ public void serializeTo(CodedOutputStream output, int fieldNumber, K key, V value)
+ throws IOException {
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(computeSerializedSize(metadata, key, value));
+ writeTo(output, metadata, key, value);
+ }
+
+ /**
+ * Computes the message size for the provided key and value as though they were wrapped
+ * by a {@link MapEntryLite}. This helper method avoids allocation of a {@link MapEntryLite}
+ * built with a key and value and is called from generated code directly.
+ */
+ public int computeMessageSize(int fieldNumber, K key, V value) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(
+ computeSerializedSize(metadata, key, value));
+ }
+
+ /**
+ * Parses an entry off of the input as a {@link Map.Entry}. This helper requires an allocation
+ * so using {@link #parseInto} is preferred if possible.
+ */
+ public Map.Entry<K, V> parseEntry(ByteString bytes, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ return parseEntry(bytes.newCodedInput(), metadata, extensionRegistry);
+ }
+
+ static <K, V> Map.Entry<K, V> parseEntry(
+ CodedInputStream input, Metadata<K, V> metadata, ExtensionRegistryLite extensionRegistry)
+ throws IOException{
+ K key = metadata.defaultKey;
+ V value = metadata.defaultValue;
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+ if (tag == WireFormat.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
+ key = parseField(input, extensionRegistry, metadata.keyType, key);
+ } else if (tag == WireFormat.makeTag(VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
+ value = parseField(input, extensionRegistry, metadata.valueType, value);
+ } else {
+ if (!input.skipField(tag)) {
+ break;
+ }
+ }
+ }
+ return new AbstractMap.SimpleImmutableEntry<K, V>(key, value);
+ }
+
+ /**
+ * Parses an entry off of the input into the map. This helper avoids allocaton of a
+ * {@link MapEntryLite} by parsing directly into the provided {@link MapFieldLite}.
+ */
+ public void parseInto(
+ MapFieldLite<K, V> map, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int length = input.readRawVarint32();
+ final int oldLimit = input.pushLimit(length);
+ K key = metadata.defaultKey;
+ V value = metadata.defaultValue;
+
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+ if (tag == WireFormat.makeTag(KEY_FIELD_NUMBER, metadata.keyType.getWireType())) {
+ key = parseField(input, extensionRegistry, metadata.keyType, key);
+ } else if (tag == WireFormat.makeTag(VALUE_FIELD_NUMBER, metadata.valueType.getWireType())) {
+ value = parseField(input, extensionRegistry, metadata.valueType, value);
+ } else {
+ if (!input.skipField(tag)) {
+ break;
+ }
+ }
+ }
+
+ input.checkLastTagWas(0);
+ input.popLimit(oldLimit);
+ map.put(key, value);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java
new file mode 100644
index 0000000000..805defe29f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapField.java
@@ -0,0 +1,625 @@
+// 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Internal representation of map fields in generated messages.
+ *
+ * This class supports accessing the map field as a {@link Map} to be used in
+ * generated API and also supports accessing the field as a {@link List} to be
+ * used in reflection API. It keeps track of where the data is currently stored
+ * and do necessary conversions between map and list.
+ *
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ *
+ * THREAD-SAFETY NOTE: Read-only access is thread-safe. Users can call getMap()
+ * and getList() concurrently in multiple threads. If write-access is needed,
+ * all access must be synchronized.
+ */
+public class MapField<K, V> implements MutabilityOracle {
+ /**
+ * Indicates where the data of this map field is currently stored.
+ *
+ * MAP: Data is stored in mapData.
+ * LIST: Data is stored in listData.
+ * BOTH: mapData and listData have the same data.
+ *
+ * When the map field is accessed (through generated API or reflection API),
+ * it will shift between these 3 modes:
+ *
+ * getMap() getList() getMutableMap() getMutableList()
+ * MAP MAP BOTH MAP LIST
+ * LIST BOTH LIST MAP LIST
+ * BOTH BOTH BOTH MAP LIST
+ *
+ * As the map field changes its mode, the list/map reference returned in a
+ * previous method call may be invalidated.
+ */
+ private enum StorageMode {MAP, LIST, BOTH}
+
+ private volatile boolean isMutable;
+ private volatile StorageMode mode;
+ private MutatabilityAwareMap<K, V> mapData;
+ private List<Message> listData;
+
+ // Convert between a map entry Message and a key-value pair.
+ private static interface Converter<K, V> {
+ Message convertKeyAndValueToMessage(K key, V value);
+ void convertMessageToKeyAndValue(Message message, Map<K, V> map);
+
+ Message getMessageDefaultInstance();
+ }
+
+ private static class ImmutableMessageConverter<K, V> implements Converter<K, V> {
+ private final MapEntry<K, V> defaultEntry;
+ public ImmutableMessageConverter(MapEntry<K, V> defaultEntry) {
+ this.defaultEntry = defaultEntry;
+ }
+
+ @Override
+ public Message convertKeyAndValueToMessage(K key, V value) {
+ return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+ MapEntry<K, V> entry = (MapEntry<K, V>) message;
+ map.put(entry.getKey(), entry.getValue());
+ }
+
+ @Override
+ public Message getMessageDefaultInstance() {
+ return defaultEntry;
+ }
+ }
+
+
+ private final Converter<K, V> converter;
+
+ private MapField(
+ Converter<K, V> converter,
+ StorageMode mode,
+ Map<K, V> mapData) {
+ this.converter = converter;
+ this.isMutable = true;
+ this.mode = mode;
+ this.mapData = new MutatabilityAwareMap<K, V>(this, mapData);
+ this.listData = null;
+ }
+
+ private MapField(
+ MapEntry<K, V> defaultEntry,
+ StorageMode mode,
+ Map<K, V> mapData) {
+ this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData);
+ }
+
+
+ /** Returns an immutable empty MapField. */
+ public static <K, V> MapField<K, V> emptyMapField(
+ MapEntry<K, V> defaultEntry) {
+ return new MapField<K, V>(
+ defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap());
+ }
+
+
+ /** Creates a new mutable empty MapField. */
+ public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) {
+ return new MapField<K, V>(
+ defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
+ }
+
+
+ private Message convertKeyAndValueToMessage(K key, V value) {
+ return converter.convertKeyAndValueToMessage(key, value);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
+ converter.convertMessageToKeyAndValue(message, map);
+ }
+
+ private List<Message> convertMapToList(MutatabilityAwareMap<K, V> mapData) {
+ List<Message> listData = new ArrayList<Message>();
+ for (Map.Entry<K, V> entry : mapData.entrySet()) {
+ listData.add(
+ convertKeyAndValueToMessage(
+ entry.getKey(), entry.getValue()));
+ }
+ return listData;
+ }
+
+ private MutatabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
+ Map<K, V> mapData = new LinkedHashMap<K, V>();
+ for (Message item : listData) {
+ convertMessageToKeyAndValue(item, mapData);
+ }
+ return new MutatabilityAwareMap<K, V>(this, mapData);
+ }
+
+ /** Returns the content of this MapField as a read-only Map. */
+ public Map<K, V> getMap() {
+ if (mode == StorageMode.LIST) {
+ synchronized (this) {
+ if (mode == StorageMode.LIST) {
+ mapData = convertListToMap(listData);
+ mode = StorageMode.BOTH;
+ }
+ }
+ }
+ return Collections.unmodifiableMap(mapData);
+ }
+
+ /** Gets a mutable Map view of this MapField. */
+ public Map<K, V> getMutableMap() {
+ if (mode != StorageMode.MAP) {
+ if (mode == StorageMode.LIST) {
+ mapData = convertListToMap(listData);
+ }
+ listData = null;
+ mode = StorageMode.MAP;
+ }
+ return mapData;
+ }
+
+ public void mergeFrom(MapField<K, V> other) {
+ getMutableMap().putAll(MapFieldLite.copy(other.getMap()));
+ }
+
+ public void clear() {
+ mapData = new MutatabilityAwareMap<K, V>(this, new LinkedHashMap<K, V>());
+ mode = StorageMode.MAP;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof MapField)) {
+ return false;
+ }
+ MapField<K, V> other = (MapField<K, V>) object;
+ return MapFieldLite.<K, V>equals(getMap(), other.getMap());
+ }
+
+ @Override
+ public int hashCode() {
+ return MapFieldLite.<K, V>calculateHashCodeForMap(getMap());
+ }
+
+ /** Returns a deep copy of this MapField. */
+ public MapField<K, V> copy() {
+ return new MapField<K, V>(
+ converter, StorageMode.MAP, MapFieldLite.copy(getMap()));
+ }
+
+ /** Gets the content of this MapField as a read-only List. */
+ List<Message> getList() {
+ if (mode == StorageMode.MAP) {
+ synchronized (this) {
+ if (mode == StorageMode.MAP) {
+ listData = convertMapToList(mapData);
+ mode = StorageMode.BOTH;
+ }
+ }
+ }
+ return Collections.unmodifiableList(listData);
+ }
+
+ /** Gets a mutable List view of this MapField. */
+ List<Message> getMutableList() {
+ if (mode != StorageMode.LIST) {
+ if (mode == StorageMode.MAP) {
+ listData = convertMapToList(mapData);
+ }
+ mapData = null;
+ mode = StorageMode.LIST;
+ }
+ return listData;
+ }
+
+ /**
+ * Gets the default instance of the message stored in the list view of this
+ * map field.
+ */
+ Message getMapEntryMessageDefaultInstance() {
+ return converter.getMessageDefaultInstance();
+ }
+
+ /**
+ * Makes this list immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ public void makeImmutable() {
+ isMutable = false;
+ }
+
+ /**
+ * Returns whether this field can be modified.
+ */
+ public boolean isMutable() {
+ return isMutable;
+ }
+
+ /* (non-Javadoc)
+ * @see com.google.protobuf.MutabilityOracle#ensureMutable()
+ */
+ @Override
+ public void ensureMutable() {
+ if (!isMutable()) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * An internal map that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareMap<K, V> implements Map<K, V> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Map<K, V> delegate;
+
+ MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map<K, V> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return delegate.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return delegate.containsValue(value);
+ }
+
+ @Override
+ public V get(Object key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ mutabilityOracle.ensureMutable();
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public V remove(Object key) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(key);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ mutabilityOracle.ensureMutable();
+ delegate.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return new MutatabilityAwareSet<K>(mutabilityOracle, delegate.keySet());
+ }
+
+ @Override
+ public Collection<V> values() {
+ return new MutatabilityAwareCollection<V>(mutabilityOracle, delegate.values());
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ return new MutatabilityAwareSet<Entry<K, V>>(mutabilityOracle, delegate.entrySet());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+
+ /**
+ * An internal collection that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareCollection<E> implements Collection<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Collection<E> delegate;
+
+ MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return delegate.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ // Unsupported operation in the delegate.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ // Unsupported operation in the delegate.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.retainAll(c);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+
+ /**
+ * An internal set that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareSet<E> implements Set<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Set<E> delegate;
+
+ MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return delegate.contains(o);
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new MutatabilityAwareIterator<E>(mutabilityOracle, delegate.iterator());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return delegate.toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return delegate.toArray(a);
+ }
+
+ @Override
+ public boolean add(E e) {
+ mutabilityOracle.ensureMutable();
+ return delegate.add(e);
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ mutabilityOracle.ensureMutable();
+ return delegate.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ return delegate.containsAll(c);
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.addAll(c);
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.retainAll(c);
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ mutabilityOracle.ensureMutable();
+ return delegate.removeAll(c);
+ }
+
+ @Override
+ public void clear() {
+ mutabilityOracle.ensureMutable();
+ delegate.clear();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+
+ /**
+ * An internal iterator that checks for mutability before delegating.
+ */
+ private static class MutatabilityAwareIterator<E> implements Iterator<E> {
+ private final MutabilityOracle mutabilityOracle;
+ private final Iterator<E> delegate;
+
+ MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator<E> delegate) {
+ this.mutabilityOracle = mutabilityOracle;
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return delegate.hasNext();
+ }
+
+ @Override
+ public E next() {
+ return delegate.next();
+ }
+
+ @Override
+ public void remove() {
+ mutabilityOracle.ensureMutable();
+ delegate.remove();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return delegate.equals(obj);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapFieldLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
new file mode 100644
index 0000000000..4264027911
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -0,0 +1,224 @@
+// 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 com.google.protobuf.Internal.EnumLite;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Internal representation of map fields in generated lite-runtime messages.
+ *
+ * This class is a protobuf implementation detail. Users shouldn't use this
+ * class directly.
+ */
+public final class MapFieldLite<K, V> extends LinkedHashMap<K, V> {
+
+ private boolean isMutable;
+
+ private MapFieldLite() {
+ this.isMutable = true;
+ }
+
+ private MapFieldLite(Map<K, V> mapData) {
+ super(mapData);
+ this.isMutable = true;
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite();
+ static {
+ EMPTY_MAP_FIELD.makeImmutable();
+ }
+
+ /** Returns an singleton immutable empty MapFieldLite instance. */
+ @SuppressWarnings({"unchecked", "cast"})
+ public static <K, V> MapFieldLite<K, V> emptyMapField() {
+ return (MapFieldLite<K, V>) EMPTY_MAP_FIELD;
+ }
+
+ public void mergeFrom(MapFieldLite<K, V> other) {
+ ensureMutable();
+ if (!other.isEmpty()) {
+ putAll(other);
+ }
+ }
+
+ @SuppressWarnings({"unchecked", "cast"})
+ @Override public Set<Map.Entry<K, V>> entrySet() {
+ return isEmpty() ? Collections.<Map.Entry<K, V>>emptySet() : super.entrySet();
+ }
+
+ @Override public void clear() {
+ ensureMutable();
+ super.clear();
+ }
+
+ @Override public V put(K key, V value) {
+ ensureMutable();
+ return super.put(key, value);
+ }
+
+ public V put(Map.Entry<K, V> entry) {
+ return put(entry.getKey(), entry.getValue());
+ }
+
+ @Override public void putAll(Map<? extends K, ? extends V> m) {
+ ensureMutable();
+ super.putAll(m);
+ }
+
+ @Override public V remove(Object key) {
+ ensureMutable();
+ return super.remove(key);
+ }
+
+ private static boolean equals(Object a, Object b) {
+ if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * Checks whether two {@link Map}s are equal. We don't use the default equals
+ * method of {@link Map} because it compares by identity not by content for
+ * byte arrays.
+ */
+ static <K, V> boolean equals(Map<K, V> a, Map<K, V> b) {
+ if (a == b) {
+ return true;
+ }
+ if (a.size() != b.size()) {
+ return false;
+ }
+ for (Map.Entry<K, V> entry : a.entrySet()) {
+ if (!b.containsKey(entry.getKey())) {
+ return false;
+ }
+ if (!equals(entry.getValue(), b.get(entry.getKey()))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether two map fields are equal.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object object) {
+ return (object instanceof Map) && equals(this, (Map<K, V>) object);
+ }
+
+ private static int calculateHashCodeForObject(Object a) {
+ if (a instanceof byte[]) {
+ return Internal.hashCode((byte[]) a);
+ }
+ // Enums should be stored as integers internally.
+ if (a instanceof EnumLite) {
+ throw new UnsupportedOperationException();
+ }
+ return a.hashCode();
+ }
+
+ /**
+ * Calculates the hash code for a {@link Map}. We don't use the default hash
+ * code method of {@link Map} because for byte arrays and protobuf enums it
+ * use {@link Object#hashCode()}.
+ */
+ static <K, V> int calculateHashCodeForMap(Map<K, V> a) {
+ int result = 0;
+ for (Map.Entry<K, V> entry : a.entrySet()) {
+ result += calculateHashCodeForObject(entry.getKey())
+ ^ calculateHashCodeForObject(entry.getValue());
+ }
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return calculateHashCodeForMap(this);
+ }
+
+ private static Object copy(Object object) {
+ if (object instanceof byte[]) {
+ byte[] data = (byte[]) object;
+ return Arrays.copyOf(data, data.length);
+ }
+ return object;
+ }
+
+ /**
+ * Makes a deep copy of a {@link Map}. Immutable objects in the map will be
+ * shared (e.g., integers, strings, immutable messages) and mutable ones will
+ * have a copy (e.g., byte arrays, mutable messages).
+ */
+ @SuppressWarnings("unchecked")
+ static <K, V> Map<K, V> copy(Map<K, V> map) {
+ Map<K, V> result = new LinkedHashMap<K, V>();
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ result.put(entry.getKey(), (V) copy(entry.getValue()));
+ }
+ return result;
+ }
+
+ /** Returns a deep copy of this map field. */
+ public MapFieldLite<K, V> mutableCopy() {
+ return isEmpty() ? new MapFieldLite<K, V>() : new MapFieldLite<K, V>(this);
+ }
+
+ /**
+ * Makes this field immutable. All subsequent modifications will throw an
+ * {@link UnsupportedOperationException}.
+ */
+ public void makeImmutable() {
+ isMutable = false;
+ }
+
+ /**
+ * Returns whether this field can be modified.
+ */
+ public boolean isMutable() {
+ return isMutable;
+ }
+
+ private void ensureMutable() {
+ if (!isMutable()) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Message.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Message.java
new file mode 100644
index 0000000000..94590fb91b
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Message.java
@@ -0,0 +1,292 @@
+// 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.
+
+// TODO(kenton): Use generics? E.g. Builder<BuilderType extends Builder>, then
+// mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ * <p>
+ * See also {@link MessageLite}, which defines most of the methods that typical
+ * users care about. {@link Message} adds to it methods that are not available
+ * in the "lite" runtime. The biggest added features are introspection and
+ * reflection -- i.e., getting descriptors for the message type and accessing
+ * the field values dynamically.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface Message extends MessageLite, MessageOrBuilder {
+
+ // (From MessageLite, re-declared here only for return type covariance.)
+ @Override
+ Parser<? extends Message> getParserForType();
+
+
+ // -----------------------------------------------------------------
+ // Comparison and hashing
+
+ /**
+ * Compares the specified object with this message for equality. Returns
+ * {@code true} if the given object is a message of the same type (as
+ * defined by {@code getDescriptorForType()}) and has identical values for
+ * all of its fields. Subclasses must implement this; inheriting
+ * {@code Object.equals()} is incorrect.
+ *
+ * @param other object to be compared for equality with this message
+ * @return {@code true} if the specified object is equal to this message
+ */
+ @Override
+ boolean equals(Object other);
+
+ /**
+ * Returns the hash code value for this message. The hash code of a message
+ * should mix the message's type (object identity of the descriptor) with its
+ * contents (known and unknown field values). Subclasses must implement this;
+ * inheriting {@code Object.hashCode()} is incorrect.
+ *
+ * @return the hash code value for this message
+ * @see Map#hashCode()
+ */
+ @Override
+ int hashCode();
+
+ // -----------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Converts the message to a string in protocol buffer text format. This is
+ * just a trivial wrapper around {@link
+ * TextFormat#printToString(MessageOrBuilder)}.
+ */
+ @Override
+ String toString();
+
+ // =================================================================
+ // Builders
+
+ // (From MessageLite, re-declared here only for return type covariance.)
+ @Override
+ Builder newBuilderForType();
+
+ @Override
+ Builder toBuilder();
+
+ /**
+ * Abstract interface implemented by Protocol Message builders.
+ */
+ interface Builder extends MessageLite.Builder, MessageOrBuilder {
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
+ @Override
+ Builder clear();
+
+ /**
+ * Merge {@code other} into the message being built. {@code other} must
+ * have the exact same type as {@code this} (i.e.
+ * {@code getDescriptorForType() == other.getDescriptorForType()}).
+ *
+ * Merging occurs as follows. For each field:<br>
+ * * For singular primitive fields, if the field is set in {@code other},
+ * then {@code other}'s value overwrites the value in this message.<br>
+ * * For singular message fields, if the field is set in {@code other},
+ * it is merged into the corresponding sub-message of this message
+ * using the same merging rules.<br>
+ * * For repeated fields, the elements in {@code other} are concatenated
+ * with the elements in this message.
+ * * For oneof groups, if the other message has one of the fields set,
+ * the group of this message is cleared and replaced by the field
+ * of the other message, so that the oneof constraint is preserved.
+ *
+ * This is equivalent to the {@code Message::MergeFrom} method in C++.
+ */
+ Builder mergeFrom(Message other);
+
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
+ @Override
+ Message build();
+
+ @Override
+ Message buildPartial();
+
+ @Override
+ Builder clone();
+
+ @Override
+ Builder mergeFrom(CodedInputStream input) throws IOException;
+
+ @Override
+ Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Get the message's type's descriptor.
+ * See {@link Message#getDescriptorForType()}.
+ */
+ @Override
+ Descriptors.Descriptor getDescriptorForType();
+
+ /**
+ * Create a Builder for messages of the appropriate type for the given
+ * field. Messages built with this can then be passed to setField(),
+ * setRepeatedField(), or addRepeatedField().
+ */
+ Builder newBuilderForField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Get a nested builder instance for the given field.
+ * <p>
+ * Normally, we hold a reference to the immutable message object for the
+ * message type field. Some implementations(the generated message builders),
+ * however, can also hold a reference to the builder object (a nested
+ * builder) for the field.
+ * <p>
+ * If the field is already backed up by a nested builder, the nested builder
+ * will be returned. Otherwise, a new field builder will be created and
+ * returned. The original message field (if exist) will be merged into the
+ * field builder, which will then be nested into its parent builder.
+ * <p>
+ * NOTE: implementations that do not support nested builders will throw
+ * <code>UnsupportedOperationException</code>.
+ */
+ Builder getFieldBuilder(Descriptors.FieldDescriptor field);
+
+ /**
+ * Get a nested builder instance for the given repeated field instance.
+ * <p>
+ * Normally, we hold a reference to the immutable message object for the
+ * message type field. Some implementations(the generated message builders),
+ * however, can also hold a reference to the builder object (a nested
+ * builder) for the field.
+ * <p>
+ * If the field is already backed up by a nested builder, the nested builder
+ * will be returned. Otherwise, a new field builder will be created and
+ * returned. The original message field (if exist) will be merged into the
+ * field builder, which will then be nested into its parent builder.
+ * <p>
+ * NOTE: implementations that do not support nested builders will throw
+ * <code>UnsupportedOperationException</code>.
+ */
+ Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field,
+ int index);
+
+ /**
+ * Sets a field to the given value. The value must be of the correct type
+ * for this field, i.e. the same type that
+ * {@link Message#getField(Descriptors.FieldDescriptor)} would return.
+ */
+ Builder setField(Descriptors.FieldDescriptor field, Object value);
+
+ /**
+ * Clears the field. This is exactly equivalent to calling the generated
+ * "clear" accessor method corresponding to the field.
+ */
+ Builder clearField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Clears the oneof. This is exactly equivalent to calling the generated
+ * "clear" accessor method corresponding to the oneof.
+ */
+ Builder clearOneof(Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Sets an element of a repeated field to the given value. The value must
+ * be of the correct type for this field, i.e. the same type that
+ * {@link Message#getRepeatedField(Descriptors.FieldDescriptor,int)} would
+ * return.
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() != getDescriptorForType()}.
+ */
+ Builder setRepeatedField(Descriptors.FieldDescriptor field,
+ int index, Object value);
+
+ /**
+ * Like {@code setRepeatedField}, but appends the value as a new element.
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() != getDescriptorForType()}.
+ */
+ Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
+
+ /** Set the {@link UnknownFieldSet} for this message. */
+ Builder setUnknownFields(UnknownFieldSet unknownFields);
+
+ /**
+ * Merge some unknown fields into the {@link UnknownFieldSet} for this
+ * message.
+ */
+ Builder mergeUnknownFields(UnknownFieldSet unknownFields);
+
+ // ---------------------------------------------------------------
+ // Convenience methods.
+
+ // (From MessageLite.Builder, re-declared here only for return type
+ // covariance.)
+ @Override
+ Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(InputStream input) throws IOException;
+
+ @Override
+ Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ @Override
+ boolean mergeDelimitedFrom(InputStream input) throws IOException;
+
+ @Override
+ boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLite.java
new file mode 100644
index 0000000000..88f531df3e
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLite.java
@@ -0,0 +1,341 @@
+// 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.
+
+// TODO(kenton): Use generics? E.g. Builder<BuilderType extends Builder>, then
+// mergeFrom*() could return BuilderType for better type-safety.
+
+package com.google.protobuf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Abstract interface implemented by Protocol Message objects.
+ *
+ * <p>This interface is implemented by all protocol message objects. Non-lite
+ * messages additionally implement the Message interface, which is a subclass
+ * of MessageLite. Use MessageLite instead when you only need the subset of
+ * features which it supports -- namely, nothing that uses descriptors or
+ * reflection. You can instruct the protocol compiler to generate classes
+ * which implement only MessageLite, not the full Message interface, by adding
+ * the follow line to the .proto file:
+ * <pre>
+ * option optimize_for = LITE_RUNTIME;
+ * </pre>
+ *
+ * <p>This is particularly useful on resource-constrained systems where the
+ * full protocol buffers runtime library is too big.
+ *
+ * <p>Note that on non-constrained systems (e.g. servers) when you need to link
+ * in lots of protocol definitions, a better way to reduce total code footprint
+ * is to use {@code optimize_for = CODE_SIZE}. This will make the generated
+ * code smaller while still supporting all the same features (at the expense of
+ * speed). {@code optimize_for = LITE_RUNTIME} is best when you only have a
+ * small number of message types linked into your binary, in which case the
+ * size of the protocol buffers runtime itself is the biggest problem.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface MessageLite extends MessageLiteOrBuilder {
+
+
+ /**
+ * Serializes the message and writes it to {@code output}. This does not
+ * flush or close the stream.
+ */
+ void writeTo(CodedOutputStream output) throws IOException;
+
+ /**
+ * Get the number of bytes required to encode this message. The result
+ * is only computed on the first call and memoized after that.
+ */
+ int getSerializedSize();
+
+
+ /**
+ * Gets the parser for a message of the same type as this message.
+ */
+ Parser<? extends MessageLite> getParserForType();
+
+ // -----------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Serializes the message to a {@code ByteString} and returns it. This is
+ * just a trivial wrapper around
+ * {@link #writeTo(CodedOutputStream)}.
+ */
+ ByteString toByteString();
+
+ /**
+ * Serializes the message to a {@code byte} array and returns it. This is
+ * just a trivial wrapper around
+ * {@link #writeTo(CodedOutputStream)}.
+ */
+ byte[] toByteArray();
+
+ /**
+ * Serializes the message and writes it to {@code output}. This is just a
+ * trivial wrapper around {@link #writeTo(CodedOutputStream)}. This does
+ * not flush or close the stream.
+ * <p>
+ * NOTE: Protocol Buffers are not self-delimiting. Therefore, if you write
+ * any more data to the stream after the message, you must somehow ensure
+ * that the parser on the receiving end does not interpret this as being
+ * part of the protocol message. This can be done e.g. by writing the size
+ * of the message before the data, then making sure to limit the input to
+ * that size on the receiving end (e.g. by wrapping the InputStream in one
+ * which limits the input). Alternatively, just use
+ * {@link #writeDelimitedTo(OutputStream)}.
+ */
+ void writeTo(OutputStream output) throws IOException;
+
+ /**
+ * Like {@link #writeTo(OutputStream)}, but writes the size of the message
+ * as a varint before writing the data. This allows more data to be written
+ * to the stream after the message without the need to delimit the message
+ * data yourself. Use {@link Builder#mergeDelimitedFrom(InputStream)} (or
+ * the static method {@code YourMessageType.parseDelimitedFrom(InputStream)})
+ * to parse messages written by this method.
+ */
+ void writeDelimitedTo(OutputStream output) throws IOException;
+
+
+ // =================================================================
+ // Builders
+
+ /**
+ * Constructs a new builder for a message of the same type as this message.
+ */
+ Builder newBuilderForType();
+
+ /**
+ * Constructs a builder initialized with the current message. Use this to
+ * derive a new message from the current one.
+ */
+ Builder toBuilder();
+
+ /**
+ * Abstract interface implemented by Protocol Message builders.
+ */
+ interface Builder extends MessageLiteOrBuilder, Cloneable {
+ /** Resets all fields to their default values. */
+ Builder clear();
+
+ /**
+ * Constructs the message based on the state of the Builder. Subsequent
+ * changes to the Builder will not affect the returned message.
+ * @throws UninitializedMessageException The message is missing one or more
+ * required fields (i.e. {@link #isInitialized()} returns false).
+ * Use {@link #buildPartial()} to bypass this check.
+ */
+ MessageLite build();
+
+ /**
+ * Like {@link #build()}, but does not throw an exception if the message
+ * is missing required fields. Instead, a partial message is returned.
+ * Subsequent changes to the Builder will not affect the returned message.
+ */
+ MessageLite buildPartial();
+
+ /**
+ * Clones the Builder.
+ * @see Object#clone()
+ */
+ Builder clone();
+
+ /**
+ * Parses a message of this type from the input and merges it with this
+ * message.
+ *
+ * <p>Warning: This does not verify that all required fields are present in
+ * the input message. If you call {@link #build()} without setting all
+ * required fields, it will throw an {@link UninitializedMessageException},
+ * which is a {@code RuntimeException} and thus might not be caught. There
+ * are a few good ways to deal with this:
+ * <ul>
+ * <li>Call {@link #isInitialized()} to verify that all required fields
+ * are set before building.
+ * <li>Use {@code buildPartial()} to build, which ignores missing
+ * required fields.
+ * </ul>
+ *
+ * <p>Note: The caller should call
+ * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+ * verify that the last tag seen was the appropriate end-group tag,
+ * or zero for EOF.
+ */
+ Builder mergeFrom(CodedInputStream input) throws IOException;
+
+ /**
+ * Like {@link Builder#mergeFrom(CodedInputStream)}, but also
+ * parses extensions. The extensions that you want to be able to parse
+ * must be registered in {@code extensionRegistry}. Extensions not in
+ * the registry will be treated as unknown fields.
+ */
+ Builder mergeFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ // ---------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse {@code data} as a message of this type and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse a message of this type from {@code input} and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}. Note that this method always
+ * reads the <i>entire</i> input (unless it throws an exception). If you
+ * want it to stop earlier, you will need to wrap your input in some
+ * wrapper stream that limits reading. Or, use
+ * {@link MessageLite#writeDelimitedTo(OutputStream)} to write your message
+ * and {@link #mergeDelimitedFrom(InputStream)} to read it.
+ * <p>
+ * Despite usually reading the entire input, this does not close the stream.
+ *
+ * @return this
+ */
+ Builder mergeFrom(InputStream input) throws IOException;
+
+ /**
+ * Parse a message of this type from {@code input} and merge it with the
+ * message being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
+ *
+ * @return this
+ */
+ Builder mergeFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Merge {@code other} into the message being built. {@code other} must
+ * have the exact same type as {@code this} (i.e.
+ * {@code getClass().equals(getDefaultInstanceForType().getClass())}).
+ *
+ * Merging occurs as follows. For each field:<br>
+ * * For singular primitive fields, if the field is set in {@code other},
+ * then {@code other}'s value overwrites the value in this message.<br>
+ * * For singular message fields, if the field is set in {@code other},
+ * it is merged into the corresponding sub-message of this message
+ * using the same merging rules.<br>
+ * * For repeated fields, the elements in {@code other} are concatenated
+ * with the elements in this message.
+ * * For oneof groups, if the other message has one of the fields set,
+ * the group of this message is cleared and replaced by the field
+ * of the other message, so that the oneof constraint is preserved.
+ *
+ * This is equivalent to the {@code Message::MergeFrom} method in C++.
+ */
+ Builder mergeFrom(MessageLite other);
+
+ /**
+ * Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
+ * Instead, the size of the message (encoded as a varint) is read first,
+ * then the message data. Use
+ * {@link MessageLite#writeDelimitedTo(OutputStream)} to write messages in
+ * this format.
+ *
+ * @return True if successful, or false if the stream is at EOF when the
+ * method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
+ */
+ boolean mergeDelimitedFrom(InputStream input)
+ throws IOException;
+
+ /**
+ * Like {@link #mergeDelimitedFrom(InputStream)} but supporting extensions.
+ */
+ boolean mergeDelimitedFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
new file mode 100644
index 0000000000..818386ce58
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -0,0 +1,60 @@
+// 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;
+
+/**
+ * Base interface for methods common to {@link MessageLite}
+ * and {@link MessageLite.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageLiteOrBuilder {
+ /**
+ * Get an instance of the type with no fields set. Because no fields are set,
+ * all getters for singular fields will return default values and repeated
+ * fields will appear empty.
+ * This may or may not be a singleton. This differs from the
+ * {@code getDefaultInstance()} method of generated message classes in that
+ * this method is an abstract method of the {@code MessageLite} interface
+ * whereas {@code getDefaultInstance()} is a static method of a specific
+ * class. They return the same thing.
+ */
+ MessageLite getDefaultInstanceForType();
+
+ /**
+ * Returns true if all required fields in the message and all embedded
+ * messages are set, false otherwise.
+ *
+ * <p>See also: {@link MessageOrBuilder#getInitializationErrorString()}
+ */
+ boolean isInitialized();
+
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
new file mode 100644
index 0000000000..23373ef4cd
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
@@ -0,0 +1,239 @@
+// 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.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Helps generate {@link String} representations of {@link MessageLite} protos.
+ */
+// TODO(dweis): Fix map fields.
+final class MessageLiteToString {
+
+ private static final String LIST_SUFFIX = "List";
+ private static final String BUILDER_LIST_SUFFIX = "OrBuilderList";
+ private static final String BYTES_SUFFIX = "Bytes";
+
+ /**
+ * Returns a {@link String} representation of the {@link MessageLite} object. The first line of
+ * the {@code String} representation representation includes a comment string to uniquely identify
+ * the objcet instance. This acts as an indicator that this should not be relied on for
+ * comparisons.
+ *
+ * <p>For use by generated code only.
+ */
+ static String toString(MessageLite messageLite, String commentString) {
+ StringBuilder buffer = new StringBuilder();
+ buffer.append("# ").append(commentString);
+ reflectivePrintWithIndent(messageLite, buffer, 0);
+ return buffer.toString();
+ }
+
+ /**
+ * Reflectively prints the {@link MessageLite} to the buffer at given {@code indent} level.
+ *
+ * @param buffer the buffer to write to
+ * @param indent the number of spaces to indent the proto by
+ */
+ private static void reflectivePrintWithIndent(
+ MessageLite messageLite, StringBuilder buffer, int indent) {
+ // Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and
+ // getFooList() which might be useful for building an object's string representation.
+ Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>();
+ Map<String, Method> nameToMethod = new HashMap<String, Method>();
+ Set<String> getters = new TreeSet<String>();
+ for (Method method : messageLite.getClass().getDeclaredMethods()) {
+ nameToMethod.put(method.getName(), method);
+ if (method.getParameterTypes().length == 0) {
+ nameToNoArgMethod.put(method.getName(), method);
+
+ if (method.getName().startsWith("get")) {
+ getters.add(method.getName());
+ }
+ }
+ }
+
+ for (String getter : getters) {
+ String suffix = getter.replaceFirst("get", "");
+ if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) {
+ String camelCase = suffix.substring(0, 1).toLowerCase()
+ + suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
+ // Try to reflectively get the value and toString() the field as if it were repeated. This
+ // only works if the method names have not be proguarded out or renamed.
+ Method listMethod = nameToNoArgMethod.get("get" + suffix);
+ if (listMethod != null && listMethod.getReturnType().equals(List.class)) {
+ printField(
+ buffer,
+ indent,
+ camelCaseToSnakeCase(camelCase),
+ GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
+ continue;
+ }
+ }
+
+ Method setter = nameToMethod.get("set" + suffix);
+ if (setter == null) {
+ continue;
+ }
+ if (suffix.endsWith(BYTES_SUFFIX)
+ && nameToNoArgMethod.containsKey(
+ "get" + suffix.substring(0, suffix.length() - "Bytes".length()))) {
+ // Heuristic to skip bytes based accessors for string fields.
+ continue;
+ }
+
+ String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
+
+ // Try to reflectively get the value and toString() the field as if it were optional. This
+ // only works if the method names have not be proguarded out or renamed.
+ Method getMethod = nameToNoArgMethod.get("get" + suffix);
+ Method hasMethod = nameToNoArgMethod.get("has" + suffix);
+ // TODO(dweis): Fix proto3 semantics.
+ if (getMethod != null) {
+ Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
+ final boolean hasValue = hasMethod == null
+ ? !isDefaultValue(value)
+ : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
+ // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
+ if (hasValue) {
+ printField(
+ buffer,
+ indent,
+ camelCaseToSnakeCase(camelCase),
+ value);
+ }
+ continue;
+ }
+ }
+
+ if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) {
+ Iterator<Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object>> iter =
+ ((GeneratedMessageLite.ExtendableMessage<?, ?>) messageLite).extensions.iterator();
+ while (iter.hasNext()) {
+ Map.Entry<GeneratedMessageLite.ExtensionDescriptor, Object> entry = iter.next();
+ printField(buffer, indent, "[" + entry.getKey().getNumber() + "]", entry.getValue());
+ }
+ }
+
+ if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields != null) {
+ ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent);
+ }
+ }
+
+ private static boolean isDefaultValue(Object o) {
+ if (o instanceof Boolean) {
+ return !((Boolean) o);
+ }
+ if (o instanceof Integer) {
+ return ((Integer) o) == 0;
+ }
+ if (o instanceof Float) {
+ return ((Float) o) == 0f;
+ }
+ if (o instanceof Double) {
+ return ((Double) o) == 0d;
+ }
+ if (o instanceof String) {
+ return o.equals("");
+ }
+ if (o instanceof ByteString) {
+ return o.equals(ByteString.EMPTY);
+ }
+ if (o instanceof MessageLite) { // Can happen in oneofs.
+ return o == ((MessageLite) o).getDefaultInstanceForType();
+ }
+ if (o instanceof java.lang.Enum<?>) { // Catches oneof enums.
+ return ((java.lang.Enum<?>) o).ordinal() == 0;
+ }
+
+ return false;
+ }
+
+ /**
+ * Formats a text proto field.
+ *
+ * <p>For use by generated code only.
+ *
+ * @param buffer the buffer to write to
+ * @param indent the number of spaces the proto should be indented by
+ * @param name the field name (in lower underscore case)
+ * @param object the object value of the field
+ */
+ static final void printField(StringBuilder buffer, int indent, String name, Object object) {
+ if (object instanceof List<?>) {
+ List<?> list = (List<?>) object;
+ for (Object entry : list) {
+ printField(buffer, indent, name, entry);
+ }
+ return;
+ }
+
+ buffer.append('\n');
+ for (int i = 0; i < indent; i++) {
+ buffer.append(' ');
+ }
+ buffer.append(name);
+
+ if (object instanceof String) {
+ buffer.append(": \"").append(TextFormatEscaper.escapeText((String) object)).append('"');
+ } else if (object instanceof ByteString) {
+ buffer.append(": \"").append(TextFormatEscaper.escapeBytes((ByteString) object)).append('"');
+ } else if (object instanceof GeneratedMessageLite) {
+ buffer.append(" {");
+ reflectivePrintWithIndent((GeneratedMessageLite<?, ?>) object, buffer, indent + 2);
+ buffer.append("\n");
+ for (int i = 0; i < indent; i++) {
+ buffer.append(' ');
+ }
+ buffer.append("}");
+ } else {
+ buffer.append(": ").append(object.toString());
+ }
+ }
+
+ private static final String camelCaseToSnakeCase(String camelCase) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < camelCase.length(); i++) {
+ char ch = camelCase.charAt(i);
+ if (Character.isUpperCase(ch)) {
+ builder.append("_");
+ }
+ builder.append(Character.toLowerCase(ch));
+ }
+ return builder.toString();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
new file mode 100644
index 0000000000..5e7d782132
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -0,0 +1,143 @@
+// 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.util.List;
+import java.util.Map;
+
+/**
+ * Base interface for methods common to {@link Message} and
+ * {@link Message.Builder} to provide type equivalency.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public interface MessageOrBuilder extends MessageLiteOrBuilder {
+
+ // (From MessageLite, re-declared here only for return type covariance.)
+ @Override
+ Message getDefaultInstanceForType();
+
+ /**
+ * Returns a list of field paths (e.g. "foo.bar.baz") of required fields
+ * which are not set in this message. You should call
+ * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+ * are any missing fields, as that method is likely to be much faster
+ * than this one even when the message is fully-initialized.
+ */
+ List<String> findInitializationErrors();
+
+ /**
+ * Returns a comma-delimited list of required fields which are not set
+ * in this message object. You should call
+ * {@link MessageLiteOrBuilder#isInitialized()} first to check if there
+ * are any missing fields, as that method is likely to be much faster
+ * than this one even when the message is fully-initialized.
+ */
+ String getInitializationErrorString();
+
+ /**
+ * Get the message's type's descriptor. This differs from the
+ * {@code getDescriptor()} method of generated message classes in that
+ * this method is an abstract method of the {@code Message} interface
+ * whereas {@code getDescriptor()} is a static method of a specific class.
+ * They return the same thing.
+ */
+ Descriptors.Descriptor getDescriptorForType();
+
+ /**
+ * Returns a collection of all the fields in this message which are set
+ * and their corresponding values. A singular ("required" or "optional")
+ * field is set iff hasField() returns true for that field. A "repeated"
+ * field is set iff getRepeatedFieldCount() is greater than zero. The
+ * values are exactly what would be returned by calling
+ * {@link #getField(Descriptors.FieldDescriptor)} for each field. The map
+ * is guaranteed to be a sorted map, so iterating over it will return fields
+ * in order by field number.
+ * <br>
+ * If this is for a builder, the returned map may or may not reflect future
+ * changes to the builder. Either way, the returned map is itself
+ * unmodifiable.
+ */
+ Map<Descriptors.FieldDescriptor, Object> getAllFields();
+
+ /**
+ * Returns true if the given oneof is set.
+ * @throws IllegalArgumentException if
+ * {@code oneof.getContainingType() != getDescriptorForType()}.
+ */
+ boolean hasOneof(Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Obtains the FieldDescriptor if the given oneof is set. Returns null
+ * if no field is set.
+ */
+ Descriptors.FieldDescriptor getOneofFieldDescriptor(
+ Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Returns true if the given field is set. This is exactly equivalent to
+ * calling the generated "has" accessor method corresponding to the field.
+ * @throws IllegalArgumentException The field is a repeated field, or
+ * {@code field.getContainingType() != getDescriptorForType()}.
+ */
+ boolean hasField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Obtains the value of the given field, or the default value if it is
+ * not set. For primitive fields, the boxed primitive value is returned.
+ * For enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned.
+ */
+ Object getField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Gets the number of elements of a repeated field. This is exactly
+ * equivalent to calling the generated "Count" accessor method corresponding
+ * to the field.
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() != getDescriptorForType()}.
+ */
+ int getRepeatedFieldCount(Descriptors.FieldDescriptor field);
+
+ /**
+ * Gets an element of a repeated field. For primitive fields, the boxed
+ * primitive value is returned. For enum fields, the EnumValueDescriptor
+ * for the value is returned. For embedded message fields, the sub-message
+ * is returned.
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() != getDescriptorForType()}.
+ */
+ Object getRepeatedField(Descriptors.FieldDescriptor field, int index);
+
+ /** Get the {@link UnknownFieldSet} for this message. */
+ UnknownFieldSet getUnknownFields();
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageReflection.java
new file mode 100644
index 0000000000..3d73efb3a0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MessageReflection.java
@@ -0,0 +1,990 @@
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Reflection utility methods shared by both mutable and immutable messages.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+class MessageReflection {
+
+ static void writeMessageTo(
+ Message message,
+ Map<FieldDescriptor, Object> fields,
+ CodedOutputStream output,
+ boolean alwaysWriteRequiredFields)
+ throws IOException {
+ final boolean isMessageSet =
+ message.getDescriptorForType().getOptions().getMessageSetWireFormat();
+ if (alwaysWriteRequiredFields) {
+ fields = new TreeMap<FieldDescriptor, Object>(fields);
+ for (final FieldDescriptor field :
+ message.getDescriptorForType().getFields()) {
+ if (field.isRequired() && !fields.containsKey(field)) {
+ fields.put(field, message.getField(field));
+ }
+ }
+ }
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+ fields.entrySet()) {
+ final Descriptors.FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+ if (isMessageSet && field.isExtension() &&
+ field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+ !field.isRepeated()) {
+ output.writeMessageSetExtension(field.getNumber(), (Message) value);
+ } else {
+ FieldSet.writeField(field, value, output);
+ }
+ }
+
+ final UnknownFieldSet unknownFields = message.getUnknownFields();
+ if (isMessageSet) {
+ unknownFields.writeAsMessageSetTo(output);
+ } else {
+ unknownFields.writeTo(output);
+ }
+ }
+
+ static int getSerializedSize(
+ Message message,
+ Map<FieldDescriptor, Object> fields) {
+ int size = 0;
+ final boolean isMessageSet =
+ message.getDescriptorForType().getOptions().getMessageSetWireFormat();
+
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+ fields.entrySet()) {
+ final Descriptors.FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+ if (isMessageSet && field.isExtension() &&
+ field.getType() == Descriptors.FieldDescriptor.Type.MESSAGE &&
+ !field.isRepeated()) {
+ size += CodedOutputStream.computeMessageSetExtensionSize(
+ field.getNumber(), (Message) value);
+ } else {
+ size += FieldSet.computeFieldSize(field, value);
+ }
+ }
+
+ final UnknownFieldSet unknownFields = message.getUnknownFields();
+ if (isMessageSet) {
+ size += unknownFields.getSerializedSizeAsMessageSet();
+ } else {
+ size += unknownFields.getSerializedSize();
+ }
+ return size;
+ }
+
+ static String delimitWithCommas(List<String> parts) {
+ StringBuilder result = new StringBuilder();
+ for (String part : parts) {
+ if (result.length() > 0) {
+ result.append(", ");
+ }
+ result.append(part);
+ }
+ return result.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ static boolean isInitialized(MessageOrBuilder message) {
+ // Check that all required fields are present.
+ for (final Descriptors.FieldDescriptor field : message
+ .getDescriptorForType()
+ .getFields()) {
+ if (field.isRequired()) {
+ if (!message.hasField(field)) {
+ return false;
+ }
+ }
+ }
+
+ // Check that embedded messages are initialized.
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+ message.getAllFields().entrySet()) {
+ final Descriptors.FieldDescriptor field = entry.getKey();
+ if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ for (final Message element
+ : (List<Message>) entry.getValue()) {
+ if (!element.isInitialized()) {
+ return false;
+ }
+ }
+ } else {
+ if (!((Message) entry.getValue()).isInitialized()) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static String subMessagePrefix(final String prefix,
+ final Descriptors.FieldDescriptor field,
+ final int index) {
+ final StringBuilder result = new StringBuilder(prefix);
+ if (field.isExtension()) {
+ result.append('(')
+ .append(field.getFullName())
+ .append(')');
+ } else {
+ result.append(field.getName());
+ }
+ if (index != -1) {
+ result.append('[')
+ .append(index)
+ .append(']');
+ }
+ result.append('.');
+ return result.toString();
+ }
+
+ private static void findMissingFields(final MessageOrBuilder message,
+ final String prefix,
+ final List<String> results) {
+ for (final Descriptors.FieldDescriptor field :
+ message.getDescriptorForType().getFields()) {
+ if (field.isRequired() && !message.hasField(field)) {
+ results.add(prefix + field.getName());
+ }
+ }
+
+ for (final Map.Entry<Descriptors.FieldDescriptor, Object> entry :
+ message.getAllFields().entrySet()) {
+ final Descriptors.FieldDescriptor field = entry.getKey();
+ final Object value = entry.getValue();
+
+ if (field.getJavaType() == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+ if (field.isRepeated()) {
+ int i = 0;
+ for (final Object element : (List) value) {
+ findMissingFields((MessageOrBuilder) element,
+ subMessagePrefix(prefix, field, i++),
+ results);
+ }
+ } else {
+ if (message.hasField(field)) {
+ findMissingFields((MessageOrBuilder) value,
+ subMessagePrefix(prefix, field, -1),
+ results);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Populates {@code this.missingFields} with the full "path" of each missing
+ * required field in the given message.
+ */
+ static List<String> findMissingFields(
+ final MessageOrBuilder message) {
+ final List<String> results = new ArrayList<String>();
+ findMissingFields(message, "", results);
+ return results;
+ }
+
+ static interface MergeTarget {
+ enum ContainerType {
+ MESSAGE, EXTENSION_SET
+ }
+
+ /**
+ * Returns the descriptor for the target.
+ */
+ public Descriptors.Descriptor getDescriptorForType();
+
+ public ContainerType getContainerType();
+
+ public ExtensionRegistry.ExtensionInfo findExtensionByName(
+ ExtensionRegistry registry, String name);
+
+ public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+ ExtensionRegistry registry, Descriptors.Descriptor containingType,
+ int fieldNumber);
+
+ /**
+ * Obtains the value of the given field, or the default value if it is not
+ * set. For primitive fields, the boxed primitive value is returned. For
+ * enum fields, the EnumValueDescriptor for the value is returned. For
+ * embedded message fields, the sub-message is returned. For repeated
+ * fields, a java.util.List is returned.
+ */
+ public Object getField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Returns true if the given field is set. This is exactly equivalent to
+ * calling the generated "has" accessor method corresponding to the field.
+ *
+ * @throws IllegalArgumentException The field is a repeated field, or {@code
+ * field.getContainingType() != getDescriptorForType()}.
+ */
+ boolean hasField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Sets a field to the given value. The value must be of the correct type
+ * for this field, i.e. the same type that
+ * {@link Message#getField(Descriptors.FieldDescriptor)}
+ * would return.
+ */
+ MergeTarget setField(Descriptors.FieldDescriptor field, Object value);
+
+ /**
+ * Clears the field. This is exactly equivalent to calling the generated
+ * "clear" accessor method corresponding to the field.
+ */
+ MergeTarget clearField(Descriptors.FieldDescriptor field);
+
+ /**
+ * Sets an element of a repeated field to the given value. The value must
+ * be of the correct type for this field, i.e. the same type that {@link
+ * Message#getRepeatedField(Descriptors.FieldDescriptor, int)} would return.
+ *
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() !=
+ * getDescriptorForType()}.
+ */
+ MergeTarget setRepeatedField(Descriptors.FieldDescriptor field,
+ int index, Object value);
+
+ /**
+ * Like {@code setRepeatedField}, but appends the value as a new element.
+ *
+ * @throws IllegalArgumentException The field is not a repeated field, or
+ * {@code field.getContainingType() !=
+ * getDescriptorForType()}.
+ */
+ MergeTarget addRepeatedField(Descriptors.FieldDescriptor field,
+ Object value);
+
+ /**
+ * Returns true if the given oneof is set.
+ *
+ * @throws IllegalArgumentException if
+ * {@code oneof.getContainingType() != getDescriptorForType()}.
+ */
+ boolean hasOneof(Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Clears the oneof. This is exactly equivalent to calling the generated
+ * "clear" accessor method corresponding to the oneof.
+ */
+ MergeTarget clearOneof(Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Obtains the FieldDescriptor if the given oneof is set. Returns null
+ * if no field is set.
+ */
+ Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof);
+
+ /**
+ * Parse the input stream into a sub field group defined based on either
+ * FieldDescriptor or the default instance.
+ */
+ Object parseGroup(CodedInputStream input, ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+ throws IOException;
+
+ /**
+ * Parse the input stream into a sub field message defined based on either
+ * FieldDescriptor or the default instance.
+ */
+ Object parseMessage(CodedInputStream input, ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+ throws IOException;
+
+ /**
+ * Parse from a ByteString into a sub field message defined based on either
+ * FieldDescriptor or the default instance. There isn't a varint indicating
+ * the length of the message at the beginning of the input ByteString.
+ */
+ Object parseMessageFromBytes(
+ ByteString bytes, ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor descriptor, Message defaultInstance)
+ throws IOException;
+
+ /**
+ * Returns the UTF8 validation level for the field.
+ */
+ WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor
+ descriptor);
+
+ /**
+ * Returns a new merge target for a sub-field. When defaultInstance is
+ * provided, it indicates the descriptor is for an extension type, and
+ * implementations should create a new instance from the defaultInstance
+ * prototype directly.
+ */
+ MergeTarget newMergeTargetForField(
+ Descriptors.FieldDescriptor descriptor,
+ Message defaultInstance);
+
+ /**
+ * Finishes the merge and returns the underlying object.
+ */
+ Object finish();
+ }
+
+ static class BuilderAdapter implements MergeTarget {
+
+ private final Message.Builder builder;
+
+ @Override
+ public Descriptors.Descriptor getDescriptorForType() {
+ return builder.getDescriptorForType();
+ }
+
+ public BuilderAdapter(Message.Builder builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return builder.getField(field);
+ }
+
+ @Override
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return builder.hasField(field);
+ }
+
+ @Override
+ public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
+ builder.setField(field, value);
+ return this;
+ }
+
+ @Override
+ public MergeTarget clearField(Descriptors.FieldDescriptor field) {
+ builder.clearField(field);
+ return this;
+ }
+
+ @Override
+ public MergeTarget setRepeatedField(
+ Descriptors.FieldDescriptor field, int index, Object value) {
+ builder.setRepeatedField(field, index, value);
+ return this;
+ }
+
+ @Override
+ public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+ builder.addRepeatedField(field, value);
+ return this;
+ }
+
+ @Override
+ public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
+ return builder.hasOneof(oneof);
+ }
+
+ @Override
+ public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
+ builder.clearOneof(oneof);
+ return this;
+ }
+
+ @Override
+ public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
+ return builder.getOneofFieldDescriptor(oneof);
+ }
+
+ @Override
+ public ContainerType getContainerType() {
+ return ContainerType.MESSAGE;
+ }
+
+ @Override
+ public ExtensionRegistry.ExtensionInfo findExtensionByName(
+ ExtensionRegistry registry, String name) {
+ return registry.findImmutableExtensionByName(name);
+ }
+
+ @Override
+ public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+ ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
+ return registry.findImmutableExtensionByNumber(containingType,
+ fieldNumber);
+ }
+
+ @Override
+ public Object parseGroup(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder;
+ // When default instance is not null. The field is an extension field.
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ input.readGroup(field.getNumber(), subBuilder, extensionRegistry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public Object parseMessage(
+ CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder;
+ // When default instance is not null. The field is an extension field.
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ input.readMessage(subBuilder, extensionRegistry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public Object parseMessageFromBytes(
+ ByteString bytes,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder;
+ // When default instance is not null. The field is an extension field.
+ if (defaultInstance != null) {
+ subBuilder = defaultInstance.newBuilderForType();
+ } else {
+ subBuilder = builder.newBuilderForField(field);
+ }
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ subBuilder.mergeFrom(bytes, extensionRegistry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public MergeTarget newMergeTargetForField(
+ Descriptors.FieldDescriptor field, Message defaultInstance) {
+ if (defaultInstance != null) {
+ return new BuilderAdapter(
+ defaultInstance.newBuilderForType());
+ } else {
+ return new BuilderAdapter(builder.newBuilderForField(field));
+ }
+ }
+
+ @Override
+ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ if (descriptor.needsUtf8Check()) {
+ return WireFormat.Utf8Validation.STRICT;
+ }
+ // TODO(liujisi): support lazy strings for repeated fields.
+ if (!descriptor.isRepeated()
+ && builder instanceof GeneratedMessage.Builder) {
+ return WireFormat.Utf8Validation.LAZY;
+ }
+ return WireFormat.Utf8Validation.LOOSE;
+ }
+
+ @Override
+ public Object finish() {
+ return builder.buildPartial();
+ }
+ }
+
+
+ static class ExtensionAdapter implements MergeTarget {
+
+ private final FieldSet<Descriptors.FieldDescriptor> extensions;
+
+ ExtensionAdapter(FieldSet<Descriptors.FieldDescriptor> extensions) {
+ this.extensions = extensions;
+ }
+
+ @Override
+ public Descriptors.Descriptor getDescriptorForType() {
+ throw new UnsupportedOperationException(
+ "getDescriptorForType() called on FieldSet object");
+ }
+
+ @Override
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return extensions.getField(field);
+ }
+
+ @Override
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return extensions.hasField(field);
+ }
+
+ @Override
+ public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
+ extensions.setField(field, value);
+ return this;
+ }
+
+ @Override
+ public MergeTarget clearField(Descriptors.FieldDescriptor field) {
+ extensions.clearField(field);
+ return this;
+ }
+
+ @Override
+ public MergeTarget setRepeatedField(
+ Descriptors.FieldDescriptor field, int index, Object value) {
+ extensions.setRepeatedField(field, index, value);
+ return this;
+ }
+
+ @Override
+ public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+ extensions.addRepeatedField(field, value);
+ return this;
+ }
+
+ @Override
+ public boolean hasOneof(Descriptors.OneofDescriptor oneof) {
+ return false;
+ }
+
+ @Override
+ public MergeTarget clearOneof(Descriptors.OneofDescriptor oneof) {
+ // Nothing to clear.
+ return this;
+ }
+
+ @Override
+ public Descriptors.FieldDescriptor getOneofFieldDescriptor(Descriptors.OneofDescriptor oneof) {
+ return null;
+ }
+
+ @Override
+ public ContainerType getContainerType() {
+ return ContainerType.EXTENSION_SET;
+ }
+
+ @Override
+ public ExtensionRegistry.ExtensionInfo findExtensionByName(
+ ExtensionRegistry registry, String name) {
+ return registry.findImmutableExtensionByName(name);
+ }
+
+ @Override
+ public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
+ ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
+ return registry.findImmutableExtensionByNumber(containingType,
+ fieldNumber);
+ }
+
+ @Override
+ public Object parseGroup(
+ CodedInputStream input,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder =
+ defaultInstance.newBuilderForType();
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ input.readGroup(field.getNumber(), subBuilder, registry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public Object parseMessage(
+ CodedInputStream input,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder =
+ defaultInstance.newBuilderForType();
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ input.readMessage(subBuilder, registry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public Object parseMessageFromBytes(
+ ByteString bytes,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
+ Message.Builder subBuilder = defaultInstance.newBuilderForType();
+ if (!field.isRepeated()) {
+ Message originalMessage = (Message) getField(field);
+ if (originalMessage != null) {
+ subBuilder.mergeFrom(originalMessage);
+ }
+ }
+ subBuilder.mergeFrom(bytes, registry);
+ return subBuilder.buildPartial();
+ }
+
+ @Override
+ public MergeTarget newMergeTargetForField(
+ Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
+ throw new UnsupportedOperationException(
+ "newMergeTargetForField() called on FieldSet object");
+ }
+
+ @Override
+ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ if (descriptor.needsUtf8Check()) {
+ return WireFormat.Utf8Validation.STRICT;
+ }
+ // TODO(liujisi): support lazy strings for ExtesnsionSet.
+ return WireFormat.Utf8Validation.LOOSE;
+ }
+
+ @Override
+ public Object finish() {
+ throw new UnsupportedOperationException(
+ "finish() called on FieldSet object");
+ }
+ }
+
+ /**
+ * Parses a single field into MergeTarget. The target can be Message.Builder,
+ * FieldSet or MutableMessage.
+ *
+ * Package-private because it is used by GeneratedMessage.ExtendableMessage.
+ *
+ * @param tag The tag, which should have already been read.
+ * @return {@code true} unless the tag is an end-group tag.
+ */
+ static boolean mergeFieldFrom(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptors.Descriptor type,
+ MergeTarget target,
+ int tag) throws IOException {
+ if (type.getOptions().getMessageSetWireFormat() &&
+ tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
+ mergeMessageSetExtensionFromCodedStream(
+ input, unknownFields, extensionRegistry, type, target);
+ return true;
+ }
+
+ final int wireType = WireFormat.getTagWireType(tag);
+ final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+
+ final Descriptors.FieldDescriptor field;
+ Message defaultInstance = null;
+
+ if (type.isExtensionNumber(fieldNumber)) {
+ // extensionRegistry may be either ExtensionRegistry or
+ // ExtensionRegistryLite. Since the type we are parsing is a full
+ // message, only a full ExtensionRegistry could possibly contain
+ // extensions of it. Otherwise we will treat the registry as if it
+ // were empty.
+ if (extensionRegistry instanceof ExtensionRegistry) {
+ final ExtensionRegistry.ExtensionInfo extension =
+ target.findExtensionByNumber((ExtensionRegistry) extensionRegistry,
+ type, fieldNumber);
+ if (extension == null) {
+ field = null;
+ } else {
+ field = extension.descriptor;
+ defaultInstance = extension.defaultInstance;
+ if (defaultInstance == null &&
+ field.getJavaType()
+ == Descriptors.FieldDescriptor.JavaType.MESSAGE) {
+ throw new IllegalStateException(
+ "Message-typed extension lacked default instance: " +
+ field.getFullName());
+ }
+ }
+ } else {
+ field = null;
+ }
+ } else if (target.getContainerType() == MergeTarget.ContainerType.MESSAGE) {
+ field = type.findFieldByNumber(fieldNumber);
+ } else {
+ field = null;
+ }
+
+ boolean unknown = false;
+ boolean packed = false;
+ if (field == null) {
+ unknown = true; // Unknown field.
+ } else if (wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ false /* isPacked */)) {
+ packed = false;
+ } else if (field.isPackable() &&
+ wireType == FieldSet.getWireFormatForFieldType(
+ field.getLiteType(),
+ true /* isPacked */)) {
+ packed = true;
+ } else {
+ unknown = true; // Unknown wire type.
+ }
+
+ if (unknown) { // Unknown field or wrong wire type. Skip.
+ return unknownFields.mergeFieldFrom(tag, input);
+ }
+
+ if (packed) {
+ final int length = input.readRawVarint32();
+ final int limit = input.pushLimit(length);
+ if (field.getLiteType() == WireFormat.FieldType.ENUM) {
+ while (input.getBytesUntilLimit() > 0) {
+ final int rawValue = input.readEnum();
+ if (field.getFile().supportsUnknownEnumValue()) {
+ target.addRepeatedField(field,
+ field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue));
+ } else {
+ final Object value = field.getEnumType().findValueByNumber(rawValue);
+ if (value == null) {
+ // If the number isn't recognized as a valid value for this
+ // enum, drop it (don't even add it to unknownFields).
+ return true;
+ }
+ target.addRepeatedField(field, value);
+ }
+ }
+ } else {
+ while (input.getBytesUntilLimit() > 0) {
+ final Object value = WireFormat.readPrimitiveField(
+ input, field.getLiteType(), target.getUtf8Validation(field));
+ target.addRepeatedField(field, value);
+ }
+ }
+ input.popLimit(limit);
+ } else {
+ final Object value;
+ switch (field.getType()) {
+ case GROUP: {
+ value = target
+ .parseGroup(input, extensionRegistry, field, defaultInstance);
+ break;
+ }
+ case MESSAGE: {
+ value = target
+ .parseMessage(input, extensionRegistry, field, defaultInstance);
+ break;
+ }
+ case ENUM:
+ final int rawValue = input.readEnum();
+ if (field.getFile().supportsUnknownEnumValue()) {
+ value = field.getEnumType().findValueByNumberCreatingIfUnknown(rawValue);
+ } else {
+ value = field.getEnumType().findValueByNumber(rawValue);
+ // If the number isn't recognized as a valid value for this enum,
+ // drop it.
+ if (value == null) {
+ unknownFields.mergeVarintField(fieldNumber, rawValue);
+ return true;
+ }
+ }
+ break;
+ default:
+ value = WireFormat.readPrimitiveField(
+ input, field.getLiteType(), target.getUtf8Validation(field));
+ break;
+ }
+
+ if (field.isRepeated()) {
+ target.addRepeatedField(field, value);
+ } else {
+ target.setField(field, value);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Called by {@code #mergeFieldFrom()} to parse a MessageSet extension into
+ * MergeTarget.
+ */
+ private static void mergeMessageSetExtensionFromCodedStream(
+ CodedInputStream input,
+ UnknownFieldSet.Builder unknownFields,
+ ExtensionRegistryLite extensionRegistry,
+ Descriptors.Descriptor type,
+ MergeTarget target) throws IOException {
+
+ // The wire format for MessageSet is:
+ // message MessageSet {
+ // repeated group Item = 1 {
+ // required int32 typeId = 2;
+ // required bytes message = 3;
+ // }
+ // }
+ // "typeId" is the extension's field number. The extension can only be
+ // a message type, where "message" contains the encoded bytes of that
+ // message.
+ //
+ // In practice, we will probably never see a MessageSet item in which
+ // the message appears before the type ID, or where either field does not
+ // appear exactly once. However, in theory such cases are valid, so we
+ // should be prepared to accept them.
+
+ int typeId = 0;
+ ByteString rawBytes = null; // If we encounter "message" before "typeId"
+ ExtensionRegistry.ExtensionInfo extension = null;
+
+ // Read bytes from input, if we get it's type first then parse it eagerly,
+ // otherwise we store the raw bytes in a local variable.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+ typeId = input.readUInt32();
+ if (typeId != 0) {
+ // extensionRegistry may be either ExtensionRegistry or
+ // ExtensionRegistryLite. Since the type we are parsing is a full
+ // message, only a full ExtensionRegistry could possibly contain
+ // extensions of it. Otherwise we will treat the registry as if it
+ // were empty.
+ if (extensionRegistry instanceof ExtensionRegistry) {
+ extension = target.findExtensionByNumber(
+ (ExtensionRegistry) extensionRegistry, type, typeId);
+ }
+ }
+
+ } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+ if (typeId != 0) {
+ if (extension != null &&
+ ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ // We already know the type, so we can parse directly from the
+ // input with no copying. Hooray!
+ eagerlyMergeMessageSetExtension(
+ input, extension, extensionRegistry, target);
+ rawBytes = null;
+ continue;
+ }
+ }
+ // We haven't seen a type ID yet or we want parse message lazily.
+ rawBytes = input.readBytes();
+
+ } else { // Unknown tag. Skip it.
+ if (!input.skipField(tag)) {
+ break; // End of group
+ }
+ }
+ }
+ input.checkLastTagWas(WireFormat.MESSAGE_SET_ITEM_END_TAG);
+
+ // Process the raw bytes.
+ if (rawBytes != null && typeId != 0) { // Zero is not a valid type ID.
+ if (extension != null) { // We known the type
+ mergeMessageSetExtensionFromBytes(
+ rawBytes, extension, extensionRegistry, target);
+ } else { // We don't know how to parse this. Ignore it.
+ if (rawBytes != null) {
+ unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(rawBytes).build());
+ }
+ }
+ }
+ }
+
+ private static void mergeMessageSetExtensionFromBytes(
+ ByteString rawBytes,
+ ExtensionRegistry.ExtensionInfo extension,
+ ExtensionRegistryLite extensionRegistry,
+ MergeTarget target) throws IOException {
+
+ Descriptors.FieldDescriptor field = extension.descriptor;
+ boolean hasOriginalValue = target.hasField(field);
+
+ if (hasOriginalValue || ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ // If the field already exists, we just parse the field.
+ Object value = target.parseMessageFromBytes(
+ rawBytes, extensionRegistry,field, extension.defaultInstance);
+ target.setField(field, value);
+ } else {
+ // Use LazyField to load MessageSet lazily.
+ LazyField lazyField = new LazyField(
+ extension.defaultInstance, extensionRegistry, rawBytes);
+ target.setField(field, lazyField);
+ }
+ }
+
+ private static void eagerlyMergeMessageSetExtension(
+ CodedInputStream input,
+ ExtensionRegistry.ExtensionInfo extension,
+ ExtensionRegistryLite extensionRegistry,
+ MergeTarget target) throws IOException {
+ Descriptors.FieldDescriptor field = extension.descriptor;
+ Object value = target.parseMessage(input, extensionRegistry, field,
+ extension.defaultInstance);
+ target.setField(field, value);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java
new file mode 100644
index 0000000000..82b723c95d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/MutabilityOracle.java
@@ -0,0 +1,48 @@
+// 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;
+
+/**
+ * Verifies that an object is mutable, throwing if not.
+ */
+interface MutabilityOracle {
+ static final MutabilityOracle IMMUTABLE = new MutabilityOracle() {
+ @Override
+ public void ensureMutable() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if not mutable.
+ */
+ void ensureMutable();
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/NioByteString.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/NioByteString.java
new file mode 100644
index 0000000000..76594809e8
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/NioByteString.java
@@ -0,0 +1,291 @@
+// 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 static com.google.protobuf.Internal.checkNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link ByteString} that wraps around a {@link ByteBuffer}.
+ */
+final class NioByteString extends ByteString.LeafByteString {
+ private final ByteBuffer buffer;
+
+ NioByteString(ByteBuffer buffer) {
+ checkNotNull(buffer, "buffer");
+
+ // Use native byte order for fast fixed32/64 operations.
+ this.buffer = buffer.slice().order(ByteOrder.nativeOrder());
+ }
+
+ // =================================================================
+ // Serializable
+
+ /**
+ * Magic method that lets us override serialization behavior.
+ */
+ private Object writeReplace() {
+ return ByteString.copyFrom(buffer.slice());
+ }
+
+ /**
+ * Magic method that lets us override deserialization behavior.
+ */
+ private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
+ throw new InvalidObjectException("NioByteString instances are not to be serialized directly");
+ }
+
+ // =================================================================
+
+ @Override
+ public byte byteAt(int index) {
+ try {
+ return buffer.get(index);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw e;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ArrayIndexOutOfBoundsException(e.getMessage());
+ }
+ }
+
+ @Override
+ public int size() {
+ return buffer.remaining();
+ }
+
+ @Override
+ public ByteString substring(int beginIndex, int endIndex) {
+ try {
+ ByteBuffer slice = slice(beginIndex, endIndex);
+ return new NioByteString(slice);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw e;
+ } catch (IndexOutOfBoundsException e) {
+ throw new ArrayIndexOutOfBoundsException(e.getMessage());
+ }
+ }
+
+ @Override
+ protected void copyToInternal(
+ byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
+ ByteBuffer slice = buffer.slice();
+ slice.position(sourceOffset);
+ slice.get(target, targetOffset, numberToCopy);
+ }
+
+ @Override
+ public void copyTo(ByteBuffer target) {
+ target.put(buffer.slice());
+ }
+
+ @Override
+ public void writeTo(OutputStream out) throws IOException {
+ out.write(toByteArray());
+ }
+
+ @Override
+ boolean equalsRange(ByteString other, int offset, int length) {
+ return substring(0, length).equals(other.substring(offset, offset + length));
+ }
+
+ @Override
+ void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) throws IOException {
+ if (buffer.hasArray()) {
+ // Optimized write for array-backed buffers.
+ // Note that we're taking the risk that a malicious OutputStream could modify the array.
+ int bufferOffset = buffer.arrayOffset() + buffer.position() + sourceOffset;
+ out.write(buffer.array(), bufferOffset, numberToWrite);
+ return;
+ }
+
+ ByteBufferWriter.write(slice(sourceOffset, sourceOffset + numberToWrite), out);
+ }
+
+ @Override
+ void writeTo(ByteOutput output) throws IOException {
+ output.writeLazy(buffer.slice());
+ }
+
+ @Override
+ public ByteBuffer asReadOnlyByteBuffer() {
+ return buffer.asReadOnlyBuffer();
+ }
+
+ @Override
+ public List<ByteBuffer> asReadOnlyByteBufferList() {
+ return Collections.singletonList(asReadOnlyByteBuffer());
+ }
+
+ @Override
+ protected String toStringInternal(Charset charset) {
+ final byte[] bytes;
+ final int offset;
+ final int length;
+ if (buffer.hasArray()) {
+ bytes = buffer.array();
+ offset = buffer.arrayOffset() + buffer.position();
+ length = buffer.remaining();
+ } else {
+ // TODO(nathanmittler): Can we optimize this?
+ bytes = toByteArray();
+ offset = 0;
+ length = bytes.length;
+ }
+ return new String(bytes, offset, length, charset);
+ }
+
+ @Override
+ public boolean isValidUtf8() {
+ return Utf8.isValidUtf8(buffer);
+ }
+
+ @Override
+ protected int partialIsValidUtf8(int state, int offset, int length) {
+ return Utf8.partialIsValidUtf8(state, buffer, offset, offset + length);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof ByteString)) {
+ return false;
+ }
+ ByteString otherString = ((ByteString) other);
+ if (size() != otherString.size()) {
+ return false;
+ }
+ if (size() == 0) {
+ return true;
+ }
+ if (other instanceof NioByteString) {
+ return buffer.equals(((NioByteString) other).buffer);
+ }
+ if (other instanceof RopeByteString) {
+ return other.equals(this);
+ }
+ return buffer.equals(otherString.asReadOnlyByteBuffer());
+ }
+
+ @Override
+ protected int partialHash(int h, int offset, int length) {
+ for (int i = offset; i < offset + length; i++) {
+ h = h * 31 + buffer.get(i);
+ }
+ return h;
+ }
+
+ @Override
+ public InputStream newInput() {
+ return new InputStream() {
+ private final ByteBuffer buf = buffer.slice();
+
+ @Override
+ public void mark(int readlimit) {
+ buf.mark();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public void reset() throws IOException {
+ try {
+ buf.reset();
+ } catch (InvalidMarkException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ return buf.remaining();
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+ return buf.get() & 0xFF;
+ }
+
+ @Override
+ public int read(byte[] bytes, int off, int len) throws IOException {
+ if (!buf.hasRemaining()) {
+ return -1;
+ }
+
+ len = Math.min(len, buf.remaining());
+ buf.get(bytes, off, len);
+ return len;
+ }
+ };
+ }
+
+ @Override
+ public CodedInputStream newCodedInput() {
+ return CodedInputStream.newInstance(buffer, true);
+ }
+
+ /**
+ * Creates a slice of a range of this buffer.
+ *
+ * @param beginIndex the beginning index of the slice (inclusive).
+ * @param endIndex the end index of the slice (exclusive).
+ * @return the requested slice.
+ */
+ private ByteBuffer slice(int beginIndex, int endIndex) {
+ if (beginIndex < buffer.position() || endIndex > buffer.limit() || beginIndex > endIndex) {
+ throw new IllegalArgumentException(
+ String.format("Invalid indices [%d, %d]", beginIndex, endIndex));
+ }
+
+ ByteBuffer slice = buffer.slice();
+ slice.position(beginIndex - buffer.position());
+ slice.limit(endIndex - buffer.position());
+ return slice;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Parser.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Parser.java
new file mode 100644
index 0000000000..cfbcb44257
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Parser.java
@@ -0,0 +1,272 @@
+// 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.InputStream;
+
+/**
+ * Abstract interface for parsing Protocol Messages.
+ *
+ * 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 java.io.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.
+ *
+ * <p>Note: The caller should call
+ * {@link CodedInputStream#checkLastTagWas(int)} after calling this to
+ * verify that the last tag seen was the appropriate end-group tag,
+ * or zero for EOF.
+ */
+ public MessageType parseFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream)}, but also parses extensions.
+ * The extensions that you want to be able to parse must be registered in
+ * {@code extensionRegistry}. Extensions not in the registry will be treated
+ * as unknown fields.
+ */
+ public MessageType parseFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(CodedInputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(CodedInputStream input, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(CodedInputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ // ---------------------------------------------------------------
+ // Convenience methods.
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(ByteString data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(ByteString data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(ByteString data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ */
+ public MessageType parseFrom(byte[] data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses {@code data} as a message of {@code MessageType}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[], int, int)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data, int off, int len)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(ByteString, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data, int off, int len,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[])}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(byte[], ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(byte[] data,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parse a message of {@code MessageType} from {@code input}.
+ * This is just a small wrapper around {@link #parseFrom(CodedInputStream)}.
+ * Note that this method always reads the <i>entire</i> input (unless it
+ * throws an exception). If you want it to stop earlier, you will need to
+ * wrap your input in some wrapper stream that limits reading. Or, use
+ * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write your
+ * message and {@link #parseDelimitedFrom(InputStream)} to read it.
+ * <p>
+ * Despite usually reading the entire input, this does not close the stream.
+ */
+ public MessageType parseFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Parses a message of {@code MessageType} from {@code input}.
+ * This is just a small wrapper around
+ * {@link #parseFrom(CodedInputStream, ExtensionRegistryLite)}.
+ */
+ public MessageType parseFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseFrom(InputStream)}, but does not read util EOF.
+ * Instead, the size of message (encoded as a varint) is read first,
+ * then the message data. Use
+ * {@link MessageLite#writeDelimitedTo(java.io.OutputStream)} to write
+ * messages in this format.
+ *
+ * @return Parsed message if successful, or null if the stream is at EOF when
+ * the method starts. Any other error (including reaching EOF during
+ * parsing) will cause an exception to be thrown.
+ */
+ public MessageType parseDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream)} but supporting extensions.
+ */
+ public MessageType parseDelimitedFrom(InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream)}, but does not throw an
+ * exception if the message is missing required fields. Instead, a partial
+ * message is returned.
+ */
+ public MessageType parsePartialDelimitedFrom(InputStream input)
+ throws InvalidProtocolBufferException;
+
+ /**
+ * Like {@link #parseDelimitedFrom(InputStream, ExtensionRegistryLite)},
+ * but does not throw an exception if the message is missing required fields.
+ * Instead, a partial message is returned.
+ */
+ public MessageType parsePartialDelimitedFrom(
+ InputStream input,
+ ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
new file mode 100644
index 0000000000..81255ec291
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
@@ -0,0 +1,105 @@
+// 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 com.google.protobuf.Internal.ProtobufList;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements {@link ProtobufList} for non-primitive and {@link String} types.
+ */
+final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
+
+ private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>();
+ static {
+ EMPTY_LIST.makeImmutable();
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed safe by runtime.
+ public static <E> ProtobufArrayList<E> emptyList() {
+ return (ProtobufArrayList<E>) EMPTY_LIST;
+ }
+
+ private final List<E> list;
+
+ ProtobufArrayList() {
+ this(new ArrayList<E>(DEFAULT_CAPACITY));
+ }
+
+ private ProtobufArrayList(List<E> list) {
+ this.list = list;
+ }
+
+ @Override
+ public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) {
+ if (capacity < size()) {
+ throw new IllegalArgumentException();
+ }
+ List<E> newList = new ArrayList<E>(capacity);
+ newList.addAll(list);
+ return new ProtobufArrayList<E>(newList);
+ }
+
+ @Override
+ public void add(int index, E element) {
+ ensureIsMutable();
+ list.add(index, element);
+ modCount++;
+ }
+
+ @Override
+ public E get(int index) {
+ return list.get(index);
+ }
+
+ @Override
+ public E remove(int index) {
+ ensureIsMutable();
+ E toReturn = list.remove(index);
+ modCount++;
+ return toReturn;
+ }
+
+ @Override
+ public E set(int index, E element) {
+ ensureIsMutable();
+ E toReturn = list.set(index, element);
+ modCount++;
+ return toReturn;
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
new file mode 100644
index 0000000000..a596d30190
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
@@ -0,0 +1,59 @@
+// 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 com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+
+/**
+ * Interface of useful methods added to all enums generated by the protocol
+ * compiler.
+ */
+public interface ProtocolMessageEnum extends Internal.EnumLite {
+
+ /**
+ * Return the value's numeric value as defined in the .proto file.
+ */
+ @Override
+ int getNumber();
+
+ /**
+ * Return the value's descriptor, which contains information such as
+ * value name, number, and type.
+ */
+ EnumValueDescriptor getValueDescriptor();
+
+ /**
+ * Return the enum type's descriptor, which contains information
+ * about each defined value, etc.
+ */
+ EnumDescriptor getDescriptorForType();
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java
new file mode 100644
index 0000000000..d553b41e52
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ProtocolStringList.java
@@ -0,0 +1,48 @@
+// 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.util.List;
+
+/**
+ * An interface extending {@code List<String>} used for repeated string fields
+ * to provide optional access to the data as a list of ByteStrings. The
+ * underlying implementation stores values as either ByteStrings or Strings
+ * (see {@link LazyStringArrayList}) depending on how the value was initialized
+ * or last read, and it is often more efficient to deal with lists of
+ * ByteStrings when handling protos that have been deserialized from bytes.
+ */
+public interface ProtocolStringList extends List<String> {
+
+ /** Returns a view of the data as a list of ByteStrings. */
+ List<ByteString> asByteStringList();
+
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
new file mode 100644
index 0000000000..29f567dcde
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -0,0 +1,708 @@
+// 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.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@code RepeatedFieldBuilder} implements a structure that a protocol
+ * message uses to hold a repeated field of other protocol messages. It supports
+ * the classical use case of adding immutable {@link Message}'s to the
+ * repeated field and is highly optimized around this (no extra memory
+ * allocations and sharing of immutable arrays).
+ * <br>
+ * It also supports the additional use case of adding a {@link Message.Builder}
+ * to the repeated field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilder
+ <MType extends GeneratedMessage,
+ BType extends GeneratedMessage.Builder,
+ IType extends MessageOrBuilder>
+ implements GeneratedMessage.BuilderParent {
+
+ // Parent to send changes to.
+ private GeneratedMessage.BuilderParent parent;
+
+ // List of messages. Never null. It may be immutable, in which case
+ // isMessagesListMutable will be false. See note below.
+ private List<MType> messages;
+
+ // Whether messages is an mutable array that can be modified.
+ private boolean isMessagesListMutable;
+
+ // List of builders. May be null, in which case, no nested builders were
+ // created. If not null, entries represent the builder for that index.
+ private List<SingleFieldBuilder<MType, BType, IType>> builders;
+
+ // Here are the invariants for messages and builders:
+ // 1. messages is never null and its count corresponds to the number of items
+ // in the repeated field.
+ // 2. If builders is non-null, messages and builders MUST always
+ // contain the same number of items.
+ // 3. Entries in either array can be null, but for any index, there MUST be
+ // either a Message in messages or a builder in builders.
+ // 4. If the builder at an index is non-null, the builder is
+ // authoritative. This is the case where a Builder was set on the index.
+ // Any message in the messages array MUST be ignored.
+ // t. If the builder at an index is null, the message in the messages
+ // list is authoritative. This is the case where a Message (not a Builder)
+ // was set directly for an index.
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+ private boolean isClean;
+
+ // A view of this builder that exposes a List interface of messages. This is
+ // initialized on demand. This is fully backed by this object and all changes
+ // are reflected in it. Access to any item converts it to a message if it
+ // was a builder.
+ private MessageExternalList<MType, BType, IType> externalMessageList;
+
+ // A view of this builder that exposes a List interface of builders. This is
+ // initialized on demand. This is fully backed by this object and all changes
+ // are reflected in it. Access to any item converts it to a builder if it
+ // was a message.
+ private BuilderExternalList<MType, BType, IType> externalBuilderList;
+
+ // A view of this builder that exposes a List interface of the interface
+ // implemented by messages and builders. This is initialized on demand. This
+ // is fully backed by this object and all changes are reflected in it.
+ // Access to any item returns either a builder or message depending on
+ // what is most efficient.
+ private MessageOrBuilderExternalList<MType, BType, IType>
+ externalMessageOrBuilderList;
+
+ /**
+ * Constructs a new builder with an empty list of messages.
+ *
+ * @param messages the current list of messages
+ * @param isMessagesListMutable Whether the messages list is mutable
+ * @param parent a listener to notify of changes
+ * @param isClean whether the builder is initially marked clean
+ */
+ public RepeatedFieldBuilder(
+ List<MType> messages,
+ boolean isMessagesListMutable,
+ GeneratedMessage.BuilderParent parent,
+ boolean isClean) {
+ this.messages = messages;
+ this.isMessagesListMutable = isMessagesListMutable;
+ this.parent = parent;
+ this.isClean = isClean;
+ }
+
+ public void dispose() {
+ // Null out parent so we stop sending it invalidations.
+ parent = null;
+ }
+
+ /**
+ * Ensures that the list of messages is mutable so it can be updated. If it's
+ * immutable, a copy is made.
+ */
+ private void ensureMutableMessageList() {
+ if (!isMessagesListMutable) {
+ messages = new ArrayList<MType>(messages);
+ isMessagesListMutable = true;
+ }
+ }
+
+ /**
+ * Ensures that the list of builders is not null. If it's null, the list is
+ * created and initialized to be the same size as the messages list with
+ * null entries.
+ */
+ private void ensureBuilders() {
+ if (this.builders == null) {
+ this.builders =
+ new ArrayList<SingleFieldBuilder<MType, BType, IType>>(
+ messages.size());
+ for (int i = 0; i < messages.size(); i++) {
+ builders.add(null);
+ }
+ }
+ }
+
+ /**
+ * Gets the count of items in the list.
+ *
+ * @return the count of items in the list.
+ */
+ public int getCount() {
+ return messages.size();
+ }
+
+ /**
+ * Gets whether the list is empty.
+ *
+ * @return whether the list is empty
+ */
+ public boolean isEmpty() {
+ return messages.isEmpty();
+ }
+
+ /**
+ * Get the message at the specified index. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it.
+ *
+ * @param index the index of the message to get
+ * @return the message for the specified index
+ */
+ public MType getMessage(int index) {
+ return getMessage(index, false);
+ }
+
+ /**
+ * Get the message at the specified index. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it.
+ *
+ * @param index the index of the message to get
+ * @param forBuild this is being called for build so we want to make sure
+ * we SingleFieldBuilder.build to send dirty invalidations
+ * @return the message for the specified index
+ */
+ private MType getMessage(int index, boolean forBuild) {
+ if (this.builders == null) {
+ // We don't have any builders -- return the current Message.
+ // This is the case where no builder was created, so we MUST have a
+ // Message.
+ return messages.get(index);
+ }
+
+ SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ // We don't have a builder -- return the current message.
+ // This is the case where no builder was created for the entry at index,
+ // so we MUST have a message.
+ return messages.get(index);
+
+ } else {
+ return forBuild ? builder.build() : builder.getMessage();
+ }
+ }
+
+ /**
+ * Gets a builder for the specified index. If no builder has been created for
+ * that index, a builder is created on demand by calling
+ * {@link Message#toBuilder}.
+ *
+ * @param index the index of the message to get
+ * @return The builder for that index
+ */
+ public BType getBuilder(int index) {
+ ensureBuilders();
+ SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ MType message = messages.get(index);
+ builder = new SingleFieldBuilder<MType, BType, IType>(
+ message, this, isClean);
+ builders.set(index, builder);
+ }
+ return builder.getBuilder();
+ }
+
+ /**
+ * Gets the base class interface for the specified index. This may either be
+ * a builder or a message. It will return whatever is more efficient.
+ *
+ * @param index the index of the message to get
+ * @return the message or builder for the index as the base class interface
+ */
+ @SuppressWarnings("unchecked")
+ public IType getMessageOrBuilder(int index) {
+ if (this.builders == null) {
+ // We don't have any builders -- return the current Message.
+ // This is the case where no builder was created, so we MUST have a
+ // Message.
+ return (IType) messages.get(index);
+ }
+
+ SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ // We don't have a builder -- return the current message.
+ // This is the case where no builder was created for the entry at index,
+ // so we MUST have a message.
+ return (IType) messages.get(index);
+
+ } else {
+ return builder.getMessageOrBuilder();
+ }
+ }
+
+ /**
+ * Sets a message at the specified index replacing the existing item at
+ * that index.
+ *
+ * @param index the index to set.
+ * @param message the message to set
+ * @return the builder
+ */
+ public RepeatedFieldBuilder<MType, BType, IType> setMessage(
+ int index, MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.set(index, message);
+ if (builders != null) {
+ SingleFieldBuilder<MType, BType, IType> entry =
+ builders.set(index, null);
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends the specified element to the end of this list.
+ *
+ * @param message the message to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+ MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.add(message);
+ if (builders != null) {
+ builders.add(null);
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Inserts the specified message at the specified position in this list.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ * @param index the index at which to insert the message
+ * @param message the message to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilder<MType, BType, IType> addMessage(
+ int index, MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.add(index, message);
+ if (builders != null) {
+ builders.add(index, null);
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends all of the messages in the specified collection to the end of
+ * this list, in the order that they are returned by the specified
+ * collection's iterator.
+ *
+ * @param values the messages to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
+ Iterable<? extends MType> values) {
+ for (final MType value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+
+ // If we can inspect the size, we can more efficiently add messages.
+ int size = -1;
+ if (values instanceof Collection) {
+ @SuppressWarnings("unchecked") final
+ Collection<MType> collection = (Collection<MType>) values;
+ if (collection.size() == 0) {
+ return this;
+ }
+ size = collection.size();
+ }
+ ensureMutableMessageList();
+
+ if (size >= 0 && messages instanceof ArrayList) {
+ ((ArrayList<MType>) messages)
+ .ensureCapacity(messages.size() + size);
+ }
+
+ for (MType value : values) {
+ addMessage(value);
+ }
+
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends a new builder to the end of this list and returns the builder.
+ *
+ * @param message the message to add which is the basis of the builder
+ * @return the new builder
+ */
+ public BType addBuilder(MType message) {
+ ensureMutableMessageList();
+ ensureBuilders();
+ SingleFieldBuilder<MType, BType, IType> builder =
+ new SingleFieldBuilder<MType, BType, IType>(
+ message, this, isClean);
+ messages.add(null);
+ builders.add(builder);
+ onChanged();
+ incrementModCounts();
+ return builder.getBuilder();
+ }
+
+ /**
+ * Inserts a new builder at the specified position in this list.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ * @param index the index at which to insert the builder
+ * @param message the message to add which is the basis of the builder
+ * @return the builder
+ */
+ public BType addBuilder(int index, MType message) {
+ ensureMutableMessageList();
+ ensureBuilders();
+ SingleFieldBuilder<MType, BType, IType> builder =
+ new SingleFieldBuilder<MType, BType, IType>(
+ message, this, isClean);
+ messages.add(index, null);
+ builders.add(index, builder);
+ onChanged();
+ incrementModCounts();
+ return builder.getBuilder();
+ }
+
+ /**
+ * Removes the element at the specified position in this list. Shifts any
+ * subsequent elements to the left (subtracts one from their indices).
+ * Returns the element that was removed from the list.
+ *
+ * @param index the index at which to remove the message
+ */
+ public void remove(int index) {
+ ensureMutableMessageList();
+ messages.remove(index);
+ if (builders != null) {
+ SingleFieldBuilder<MType, BType, IType> entry =
+ builders.remove(index);
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ onChanged();
+ incrementModCounts();
+ }
+
+ /**
+ * Removes all of the elements from this list.
+ * The list will be empty after this call returns.
+ */
+ public void clear() {
+ messages = Collections.emptyList();
+ isMessagesListMutable = false;
+ if (builders != null) {
+ for (SingleFieldBuilder<MType, BType, IType> entry :
+ builders) {
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ builders = null;
+ }
+ onChanged();
+ incrementModCounts();
+ }
+
+ /**
+ * Builds the list of messages from the builder and returns them.
+ *
+ * @return an immutable list of messages
+ */
+ public List<MType> build() {
+ // Now that build has been called, we are required to dispatch
+ // invalidations.
+ isClean = true;
+
+ if (!isMessagesListMutable && builders == null) {
+ // We still have an immutable list and we never created a builder.
+ return messages;
+ }
+
+ boolean allMessagesInSync = true;
+ if (!isMessagesListMutable) {
+ // We still have an immutable list. Let's see if any of them are out
+ // of sync with their builders.
+ for (int i = 0; i < messages.size(); i++) {
+ Message message = messages.get(i);
+ SingleFieldBuilder<MType, BType, IType> builder = builders.get(i);
+ if (builder != null) {
+ if (builder.build() != message) {
+ allMessagesInSync = false;
+ break;
+ }
+ }
+ }
+ if (allMessagesInSync) {
+ // Immutable list is still in sync.
+ return messages;
+ }
+ }
+
+ // Need to make sure messages is up to date
+ ensureMutableMessageList();
+ for (int i = 0; i < messages.size(); i++) {
+ messages.set(i, getMessage(i, true));
+ }
+
+ // We're going to return our list as immutable so we mark that we can
+ // no longer update it.
+ messages = Collections.unmodifiableList(messages);
+ isMessagesListMutable = false;
+ return messages;
+ }
+
+ /**
+ * Gets a view of the builder as a list of messages. The returned list is live
+ * and will reflect any changes to the underlying builder.
+ *
+ * @return the messages in the list
+ */
+ public List<MType> getMessageList() {
+ if (externalMessageList == null) {
+ externalMessageList =
+ new MessageExternalList<MType, BType, IType>(this);
+ }
+ return externalMessageList;
+ }
+
+ /**
+ * Gets a view of the builder as a list of builders. This returned list is
+ * live and will reflect any changes to the underlying builder.
+ *
+ * @return the builders in the list
+ */
+ public List<BType> getBuilderList() {
+ if (externalBuilderList == null) {
+ externalBuilderList =
+ new BuilderExternalList<MType, BType, IType>(this);
+ }
+ return externalBuilderList;
+ }
+
+ /**
+ * Gets a view of the builder as a list of MessageOrBuilders. This returned
+ * list is live and will reflect any changes to the underlying builder.
+ *
+ * @return the builders in the list
+ */
+ public List<IType> getMessageOrBuilderList() {
+ if (externalMessageOrBuilderList == null) {
+ externalMessageOrBuilderList =
+ new MessageOrBuilderExternalList<MType, BType, IType>(this);
+ }
+ return externalMessageOrBuilderList;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ private void onChanged() {
+ if (isClean && parent != null) {
+ parent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+
+ /**
+ * Increments the mod counts so that an ConcurrentModificationException can
+ * be thrown if calling code tries to modify the builder while its iterating
+ * the list.
+ */
+ private void incrementModCounts() {
+ if (externalMessageList != null) {
+ externalMessageList.incrementModCount();
+ }
+ if (externalBuilderList != null) {
+ externalBuilderList.incrementModCount();
+ }
+ if (externalMessageOrBuilderList != null) {
+ externalMessageOrBuilderList.incrementModCount();
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of messages.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class MessageExternalList<
+ MType extends GeneratedMessage,
+ BType extends GeneratedMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<MType> implements List<MType> {
+
+ RepeatedFieldBuilder<MType, BType, IType> builder;
+
+ MessageExternalList(
+ RepeatedFieldBuilder<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public MType get(int index) {
+ return builder.getMessage(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of builders.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class BuilderExternalList<
+ MType extends GeneratedMessage,
+ BType extends GeneratedMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<BType> implements List<BType> {
+
+ RepeatedFieldBuilder<MType, BType, IType> builder;
+
+ BuilderExternalList(
+ RepeatedFieldBuilder<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public BType get(int index) {
+ return builder.getBuilder(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of builders.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class MessageOrBuilderExternalList<
+ MType extends GeneratedMessage,
+ BType extends GeneratedMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<IType> implements List<IType> {
+
+ RepeatedFieldBuilder<MType, BType, IType> builder;
+
+ MessageOrBuilderExternalList(
+ RepeatedFieldBuilder<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public IType get(int index) {
+ return builder.getMessageOrBuilder(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java
new file mode 100644
index 0000000000..77b61b5f3c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java
@@ -0,0 +1,708 @@
+// 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.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@code RepeatedFieldBuilderV3} implements a structure that a protocol
+ * message uses to hold a repeated field of other protocol messages. It supports
+ * the classical use case of adding immutable {@link Message}'s to the
+ * repeated field and is highly optimized around this (no extra memory
+ * allocations and sharing of immutable arrays).
+ * <br>
+ * It also supports the additional use case of adding a {@link Message.Builder}
+ * to the repeated field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilderV3} and {@code RepeatedFieldBuilderV3}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilderV3
+ <MType extends AbstractMessage,
+ BType extends AbstractMessage.Builder,
+ IType extends MessageOrBuilder>
+ implements AbstractMessage.BuilderParent {
+
+ // Parent to send changes to.
+ private AbstractMessage.BuilderParent parent;
+
+ // List of messages. Never null. It may be immutable, in which case
+ // isMessagesListMutable will be false. See note below.
+ private List<MType> messages;
+
+ // Whether messages is an mutable array that can be modified.
+ private boolean isMessagesListMutable;
+
+ // List of builders. May be null, in which case, no nested builders were
+ // created. If not null, entries represent the builder for that index.
+ private List<SingleFieldBuilderV3<MType, BType, IType>> builders;
+
+ // Here are the invariants for messages and builders:
+ // 1. messages is never null and its count corresponds to the number of items
+ // in the repeated field.
+ // 2. If builders is non-null, messages and builders MUST always
+ // contain the same number of items.
+ // 3. Entries in either array can be null, but for any index, there MUST be
+ // either a Message in messages or a builder in builders.
+ // 4. If the builder at an index is non-null, the builder is
+ // authoritative. This is the case where a Builder was set on the index.
+ // Any message in the messages array MUST be ignored.
+ // t. If the builder at an index is null, the message in the messages
+ // list is authoritative. This is the case where a Message (not a Builder)
+ // was set directly for an index.
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See AbstractMessage.BuilderListener.
+ private boolean isClean;
+
+ // A view of this builder that exposes a List interface of messages. This is
+ // initialized on demand. This is fully backed by this object and all changes
+ // are reflected in it. Access to any item converts it to a message if it
+ // was a builder.
+ private MessageExternalList<MType, BType, IType> externalMessageList;
+
+ // A view of this builder that exposes a List interface of builders. This is
+ // initialized on demand. This is fully backed by this object and all changes
+ // are reflected in it. Access to any item converts it to a builder if it
+ // was a message.
+ private BuilderExternalList<MType, BType, IType> externalBuilderList;
+
+ // A view of this builder that exposes a List interface of the interface
+ // implemented by messages and builders. This is initialized on demand. This
+ // is fully backed by this object and all changes are reflected in it.
+ // Access to any item returns either a builder or message depending on
+ // what is most efficient.
+ private MessageOrBuilderExternalList<MType, BType, IType>
+ externalMessageOrBuilderList;
+
+ /**
+ * Constructs a new builder with an empty list of messages.
+ *
+ * @param messages the current list of messages
+ * @param isMessagesListMutable Whether the messages list is mutable
+ * @param parent a listener to notify of changes
+ * @param isClean whether the builder is initially marked clean
+ */
+ public RepeatedFieldBuilderV3(
+ List<MType> messages,
+ boolean isMessagesListMutable,
+ AbstractMessage.BuilderParent parent,
+ boolean isClean) {
+ this.messages = messages;
+ this.isMessagesListMutable = isMessagesListMutable;
+ this.parent = parent;
+ this.isClean = isClean;
+ }
+
+ public void dispose() {
+ // Null out parent so we stop sending it invalidations.
+ parent = null;
+ }
+
+ /**
+ * Ensures that the list of messages is mutable so it can be updated. If it's
+ * immutable, a copy is made.
+ */
+ private void ensureMutableMessageList() {
+ if (!isMessagesListMutable) {
+ messages = new ArrayList<MType>(messages);
+ isMessagesListMutable = true;
+ }
+ }
+
+ /**
+ * Ensures that the list of builders is not null. If it's null, the list is
+ * created and initialized to be the same size as the messages list with
+ * null entries.
+ */
+ private void ensureBuilders() {
+ if (this.builders == null) {
+ this.builders =
+ new ArrayList<SingleFieldBuilderV3<MType, BType, IType>>(
+ messages.size());
+ for (int i = 0; i < messages.size(); i++) {
+ builders.add(null);
+ }
+ }
+ }
+
+ /**
+ * Gets the count of items in the list.
+ *
+ * @return the count of items in the list.
+ */
+ public int getCount() {
+ return messages.size();
+ }
+
+ /**
+ * Gets whether the list is empty.
+ *
+ * @return whether the list is empty
+ */
+ public boolean isEmpty() {
+ return messages.isEmpty();
+ }
+
+ /**
+ * Get the message at the specified index. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it.
+ *
+ * @param index the index of the message to get
+ * @return the message for the specified index
+ */
+ public MType getMessage(int index) {
+ return getMessage(index, false);
+ }
+
+ /**
+ * Get the message at the specified index. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it.
+ *
+ * @param index the index of the message to get
+ * @param forBuild this is being called for build so we want to make sure
+ * we SingleFieldBuilderV3.build to send dirty invalidations
+ * @return the message for the specified index
+ */
+ private MType getMessage(int index, boolean forBuild) {
+ if (this.builders == null) {
+ // We don't have any builders -- return the current Message.
+ // This is the case where no builder was created, so we MUST have a
+ // Message.
+ return messages.get(index);
+ }
+
+ SingleFieldBuilderV3<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ // We don't have a builder -- return the current message.
+ // This is the case where no builder was created for the entry at index,
+ // so we MUST have a message.
+ return messages.get(index);
+
+ } else {
+ return forBuild ? builder.build() : builder.getMessage();
+ }
+ }
+
+ /**
+ * Gets a builder for the specified index. If no builder has been created for
+ * that index, a builder is created on demand by calling
+ * {@link Message#toBuilder}.
+ *
+ * @param index the index of the message to get
+ * @return The builder for that index
+ */
+ public BType getBuilder(int index) {
+ ensureBuilders();
+ SingleFieldBuilderV3<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ MType message = messages.get(index);
+ builder = new SingleFieldBuilderV3<MType, BType, IType>(
+ message, this, isClean);
+ builders.set(index, builder);
+ }
+ return builder.getBuilder();
+ }
+
+ /**
+ * Gets the base class interface for the specified index. This may either be
+ * a builder or a message. It will return whatever is more efficient.
+ *
+ * @param index the index of the message to get
+ * @return the message or builder for the index as the base class interface
+ */
+ @SuppressWarnings("unchecked")
+ public IType getMessageOrBuilder(int index) {
+ if (this.builders == null) {
+ // We don't have any builders -- return the current Message.
+ // This is the case where no builder was created, so we MUST have a
+ // Message.
+ return (IType) messages.get(index);
+ }
+
+ SingleFieldBuilderV3<MType, BType, IType> builder = builders.get(index);
+ if (builder == null) {
+ // We don't have a builder -- return the current message.
+ // This is the case where no builder was created for the entry at index,
+ // so we MUST have a message.
+ return (IType) messages.get(index);
+
+ } else {
+ return builder.getMessageOrBuilder();
+ }
+ }
+
+ /**
+ * Sets a message at the specified index replacing the existing item at
+ * that index.
+ *
+ * @param index the index to set.
+ * @param message the message to set
+ * @return the builder
+ */
+ public RepeatedFieldBuilderV3<MType, BType, IType> setMessage(
+ int index, MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.set(index, message);
+ if (builders != null) {
+ SingleFieldBuilderV3<MType, BType, IType> entry =
+ builders.set(index, null);
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends the specified element to the end of this list.
+ *
+ * @param message the message to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilderV3<MType, BType, IType> addMessage(
+ MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.add(message);
+ if (builders != null) {
+ builders.add(null);
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Inserts the specified message at the specified position in this list.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ * @param index the index at which to insert the message
+ * @param message the message to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilderV3<MType, BType, IType> addMessage(
+ int index, MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ ensureMutableMessageList();
+ messages.add(index, message);
+ if (builders != null) {
+ builders.add(index, null);
+ }
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends all of the messages in the specified collection to the end of
+ * this list, in the order that they are returned by the specified
+ * collection's iterator.
+ *
+ * @param values the messages to add
+ * @return the builder
+ */
+ public RepeatedFieldBuilderV3<MType, BType, IType> addAllMessages(
+ Iterable<? extends MType> values) {
+ for (final MType value : values) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ }
+
+ // If we can inspect the size, we can more efficiently add messages.
+ int size = -1;
+ if (values instanceof Collection) {
+ @SuppressWarnings("unchecked") final
+ Collection<MType> collection = (Collection<MType>) values;
+ if (collection.size() == 0) {
+ return this;
+ }
+ size = collection.size();
+ }
+ ensureMutableMessageList();
+
+ if (size >= 0 && messages instanceof ArrayList) {
+ ((ArrayList<MType>) messages)
+ .ensureCapacity(messages.size() + size);
+ }
+
+ for (MType value : values) {
+ addMessage(value);
+ }
+
+ onChanged();
+ incrementModCounts();
+ return this;
+ }
+
+ /**
+ * Appends a new builder to the end of this list and returns the builder.
+ *
+ * @param message the message to add which is the basis of the builder
+ * @return the new builder
+ */
+ public BType addBuilder(MType message) {
+ ensureMutableMessageList();
+ ensureBuilders();
+ SingleFieldBuilderV3<MType, BType, IType> builder =
+ new SingleFieldBuilderV3<MType, BType, IType>(
+ message, this, isClean);
+ messages.add(null);
+ builders.add(builder);
+ onChanged();
+ incrementModCounts();
+ return builder.getBuilder();
+ }
+
+ /**
+ * Inserts a new builder at the specified position in this list.
+ * Shifts the element currently at that position (if any) and any subsequent
+ * elements to the right (adds one to their indices).
+ *
+ * @param index the index at which to insert the builder
+ * @param message the message to add which is the basis of the builder
+ * @return the builder
+ */
+ public BType addBuilder(int index, MType message) {
+ ensureMutableMessageList();
+ ensureBuilders();
+ SingleFieldBuilderV3<MType, BType, IType> builder =
+ new SingleFieldBuilderV3<MType, BType, IType>(
+ message, this, isClean);
+ messages.add(index, null);
+ builders.add(index, builder);
+ onChanged();
+ incrementModCounts();
+ return builder.getBuilder();
+ }
+
+ /**
+ * Removes the element at the specified position in this list. Shifts any
+ * subsequent elements to the left (subtracts one from their indices).
+ * Returns the element that was removed from the list.
+ *
+ * @param index the index at which to remove the message
+ */
+ public void remove(int index) {
+ ensureMutableMessageList();
+ messages.remove(index);
+ if (builders != null) {
+ SingleFieldBuilderV3<MType, BType, IType> entry =
+ builders.remove(index);
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ onChanged();
+ incrementModCounts();
+ }
+
+ /**
+ * Removes all of the elements from this list.
+ * The list will be empty after this call returns.
+ */
+ public void clear() {
+ messages = Collections.emptyList();
+ isMessagesListMutable = false;
+ if (builders != null) {
+ for (SingleFieldBuilderV3<MType, BType, IType> entry :
+ builders) {
+ if (entry != null) {
+ entry.dispose();
+ }
+ }
+ builders = null;
+ }
+ onChanged();
+ incrementModCounts();
+ }
+
+ /**
+ * Builds the list of messages from the builder and returns them.
+ *
+ * @return an immutable list of messages
+ */
+ public List<MType> build() {
+ // Now that build has been called, we are required to dispatch
+ // invalidations.
+ isClean = true;
+
+ if (!isMessagesListMutable && builders == null) {
+ // We still have an immutable list and we never created a builder.
+ return messages;
+ }
+
+ boolean allMessagesInSync = true;
+ if (!isMessagesListMutable) {
+ // We still have an immutable list. Let's see if any of them are out
+ // of sync with their builders.
+ for (int i = 0; i < messages.size(); i++) {
+ Message message = messages.get(i);
+ SingleFieldBuilderV3<MType, BType, IType> builder = builders.get(i);
+ if (builder != null) {
+ if (builder.build() != message) {
+ allMessagesInSync = false;
+ break;
+ }
+ }
+ }
+ if (allMessagesInSync) {
+ // Immutable list is still in sync.
+ return messages;
+ }
+ }
+
+ // Need to make sure messages is up to date
+ ensureMutableMessageList();
+ for (int i = 0; i < messages.size(); i++) {
+ messages.set(i, getMessage(i, true));
+ }
+
+ // We're going to return our list as immutable so we mark that we can
+ // no longer update it.
+ messages = Collections.unmodifiableList(messages);
+ isMessagesListMutable = false;
+ return messages;
+ }
+
+ /**
+ * Gets a view of the builder as a list of messages. The returned list is live
+ * and will reflect any changes to the underlying builder.
+ *
+ * @return the messages in the list
+ */
+ public List<MType> getMessageList() {
+ if (externalMessageList == null) {
+ externalMessageList =
+ new MessageExternalList<MType, BType, IType>(this);
+ }
+ return externalMessageList;
+ }
+
+ /**
+ * Gets a view of the builder as a list of builders. This returned list is
+ * live and will reflect any changes to the underlying builder.
+ *
+ * @return the builders in the list
+ */
+ public List<BType> getBuilderList() {
+ if (externalBuilderList == null) {
+ externalBuilderList =
+ new BuilderExternalList<MType, BType, IType>(this);
+ }
+ return externalBuilderList;
+ }
+
+ /**
+ * Gets a view of the builder as a list of MessageOrBuilders. This returned
+ * list is live and will reflect any changes to the underlying builder.
+ *
+ * @return the builders in the list
+ */
+ public List<IType> getMessageOrBuilderList() {
+ if (externalMessageOrBuilderList == null) {
+ externalMessageOrBuilderList =
+ new MessageOrBuilderExternalList<MType, BType, IType>(this);
+ }
+ return externalMessageOrBuilderList;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ private void onChanged() {
+ if (isClean && parent != null) {
+ parent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+
+ /**
+ * Increments the mod counts so that an ConcurrentModificationException can
+ * be thrown if calling code tries to modify the builder while its iterating
+ * the list.
+ */
+ private void incrementModCounts() {
+ if (externalMessageList != null) {
+ externalMessageList.incrementModCount();
+ }
+ if (externalBuilderList != null) {
+ externalBuilderList.incrementModCount();
+ }
+ if (externalMessageOrBuilderList != null) {
+ externalMessageOrBuilderList.incrementModCount();
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of messages.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class MessageExternalList<
+ MType extends AbstractMessage,
+ BType extends AbstractMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<MType> implements List<MType> {
+
+ RepeatedFieldBuilderV3<MType, BType, IType> builder;
+
+ MessageExternalList(
+ RepeatedFieldBuilderV3<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public MType get(int index) {
+ return builder.getMessage(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of builders.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class BuilderExternalList<
+ MType extends AbstractMessage,
+ BType extends AbstractMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<BType> implements List<BType> {
+
+ RepeatedFieldBuilderV3<MType, BType, IType> builder;
+
+ BuilderExternalList(
+ RepeatedFieldBuilderV3<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public BType get(int index) {
+ return builder.getBuilder(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+
+ /**
+ * Provides a live view of the builder as a list of builders.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ */
+ private static class MessageOrBuilderExternalList<
+ MType extends AbstractMessage,
+ BType extends AbstractMessage.Builder,
+ IType extends MessageOrBuilder>
+ extends AbstractList<IType> implements List<IType> {
+
+ RepeatedFieldBuilderV3<MType, BType, IType> builder;
+
+ MessageOrBuilderExternalList(
+ RepeatedFieldBuilderV3<MType, BType, IType> builder) {
+ this.builder = builder;
+ }
+
+ @Override
+ public int size() {
+ return this.builder.getCount();
+ }
+
+ @Override
+ public IType get(int index) {
+ return builder.getMessageOrBuilder(index);
+ }
+
+ void incrementModCount() {
+ modCount++;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RopeByteString.java
new file mode 100644
index 0000000000..6fa555df15
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -0,0 +1,897 @@
+// 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.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+/**
+ * Class to represent {@code ByteStrings} formed by concatenation of other
+ * ByteStrings, without copying the data in the pieces. The concatenation is
+ * represented as a tree whose leaf nodes are each a
+ * {@link com.google.protobuf.ByteString.LeafByteString}.
+ *
+ * <p>Most of the operation here is inspired by the now-famous paper <a
+ * href="https://web.archive.org/web/20060202015456/http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
+ * BAP95 </a> Ropes: an Alternative to Strings hans-j. boehm, russ atkinson and
+ * michael plass
+ *
+ * <p>The algorithms described in the paper have been implemented for character
+ * strings in {@code com.google.common.string.Rope} and in the c++ class {@code
+ * cord.cc}.
+ *
+ * <p>Fundamentally the Rope algorithm represents the collection of pieces as a
+ * binary tree. BAP95 uses a Fibonacci bound relating depth to a minimum
+ * sequence length, sequences that are too short relative to their depth cause a
+ * tree rebalance. More precisely, a tree of depth d is "balanced" in the
+ * terminology of BAP95 if its length is at least F(d+2), where F(n) is the
+ * n-the Fibonacci number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum
+ * lengths 1, 2, 3, 5, 8, 13,...
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+final class RopeByteString extends ByteString {
+
+ /**
+ * BAP95. Let Fn be the nth Fibonacci number. A {@link RopeByteString} of
+ * depth n is "balanced", i.e flat enough, if its length is at least Fn+2,
+ * e.g. a "balanced" {@link RopeByteString} of depth 1 must have length at
+ * least 2, of depth 4 must have length >= 8, etc.
+ *
+ * <p>There's nothing special about using the Fibonacci numbers for this, but
+ * they are a reasonable sequence for encapsulating the idea that we are OK
+ * with longer strings being encoded in deeper binary trees.
+ *
+ * <p>For 32-bit integers, this array has length 46.
+ */
+ private static final int[] minLengthByDepth;
+
+ static {
+ // Dynamically generate the list of Fibonacci numbers the first time this
+ // class is accessed.
+ List<Integer> numbers = new ArrayList<Integer>();
+
+ // we skip the first Fibonacci number (1). So instead of: 1 1 2 3 5 8 ...
+ // we have: 1 2 3 5 8 ...
+ int f1 = 1;
+ int f2 = 1;
+
+ // get all the values until we roll over.
+ while (f2 > 0) {
+ numbers.add(f2);
+ int temp = f1 + f2;
+ f1 = f2;
+ f2 = temp;
+ }
+
+ // we include this here so that we can index this array to [x + 1] in the
+ // loops below.
+ numbers.add(Integer.MAX_VALUE);
+ minLengthByDepth = new int[numbers.size()];
+ for (int i = 0; i < minLengthByDepth.length; i++) {
+ // unbox all the values
+ minLengthByDepth[i] = numbers.get(i);
+ }
+ }
+
+ private final int totalLength;
+ private final ByteString left;
+ private final ByteString right;
+ private final int leftLength;
+ private final int treeDepth;
+
+ /**
+ * Create a new RopeByteString, which can be thought of as a new tree node, by
+ * recording references to the two given strings.
+ *
+ * @param left string on the left of this node, should have {@code size() >
+ * 0}
+ * @param right string on the right of this node, should have {@code size() >
+ * 0}
+ */
+ private RopeByteString(ByteString left, ByteString right) {
+ this.left = left;
+ this.right = right;
+ leftLength = left.size();
+ totalLength = leftLength + right.size();
+ treeDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+ }
+
+ /**
+ * Concatenate the given strings while performing various optimizations to
+ * slow the growth rate of tree depth and tree node count. The result is
+ * either a {@link com.google.protobuf.ByteString.LeafByteString} or a
+ * {@link RopeByteString} depending on which optimizations, if any, were
+ * applied.
+ *
+ * <p>Small pieces of length less than {@link
+ * ByteString#CONCATENATE_BY_COPY_SIZE} may be copied by value here, as in
+ * BAP95. Large pieces are referenced without copy.
+ *
+ * @param left string on the left
+ * @param right string on the right
+ * @return concatenation representing the same sequence as the given strings
+ */
+ static ByteString concatenate(ByteString left, ByteString right) {
+ if (right.size() == 0) {
+ return left;
+ }
+
+ if (left.size() == 0) {
+ return right;
+ }
+
+ final int newLength = left.size() + right.size();
+ if (newLength < ByteString.CONCATENATE_BY_COPY_SIZE) {
+ // Optimization from BAP95: For short (leaves in paper, but just short
+ // here) total length, do a copy of data to a new leaf.
+ return concatenateBytes(left, right);
+ }
+
+ if (left instanceof RopeByteString) {
+ final RopeByteString leftRope = (RopeByteString) left;
+ if (leftRope.right.size() + right.size() < CONCATENATE_BY_COPY_SIZE) {
+ // Optimization from BAP95: As an optimization of the case where the
+ // ByteString is constructed by repeated concatenate, recognize the case
+ // where a short string is concatenated to a left-hand node whose
+ // right-hand branch is short. In the paper this applies to leaves, but
+ // we just look at the length here. This has the advantage of shedding
+ // references to unneeded data when substrings have been taken.
+ //
+ // When we recognize this case, we do a copy of the data and create a
+ // new parent node so that the depth of the result is the same as the
+ // given left tree.
+ ByteString newRight = concatenateBytes(leftRope.right, right);
+ return new RopeByteString(leftRope.left, newRight);
+ }
+
+ if (leftRope.left.getTreeDepth() > leftRope.right.getTreeDepth()
+ && leftRope.getTreeDepth() > right.getTreeDepth()) {
+ // Typically for concatenate-built strings the left-side is deeper than
+ // the right. This is our final attempt to concatenate without
+ // increasing the tree depth. We'll redo the node on the RHS. This
+ // is yet another optimization for building the string by repeatedly
+ // concatenating on the right.
+ ByteString newRight = new RopeByteString(leftRope.right, right);
+ return new RopeByteString(leftRope.left, newRight);
+ }
+ }
+
+ // Fine, we'll add a node and increase the tree depth--unless we rebalance ;^)
+ int newDepth = Math.max(left.getTreeDepth(), right.getTreeDepth()) + 1;
+ if (newLength >= minLengthByDepth[newDepth]) {
+ // The tree is shallow enough, so don't rebalance
+ return new RopeByteString(left, right);
+ }
+
+ return new Balancer().balance(left, right);
+ }
+
+ /**
+ * Concatenates two strings by copying data values. This is called in a few
+ * cases in order to reduce the growth of the number of tree nodes.
+ *
+ * @param left string on the left
+ * @param right string on the right
+ * @return string formed by copying data bytes
+ */
+ 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 ByteString.wrap(bytes); // Constructor wraps bytes
+ }
+
+ /**
+ * Create a new RopeByteString for testing only while bypassing all the
+ * defenses of {@link #concatenate(ByteString, ByteString)}. This allows
+ * testing trees of specific structure. We are also able to insert empty
+ * leaves, though these are dis-allowed, so that we can make sure the
+ * implementation can withstand their presence.
+ *
+ * @param left string on the left of this node
+ * @param right string on the right of this node
+ * @return an unsafe instance for testing only
+ */
+ static RopeByteString newInstanceForTest(ByteString left, ByteString right) {
+ return new RopeByteString(left, right);
+ }
+
+ /**
+ * 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) {
+ checkIndex(index, totalLength);
+
+ // Find the relevant piece by recursive descent
+ if (index < leftLength) {
+ return left.byteAt(index);
+ }
+
+ return right.byteAt(index - leftLength);
+ }
+
+ @Override
+ public int size() {
+ return totalLength;
+ }
+
+ // =================================================================
+ // Pieces
+
+ @Override
+ protected int getTreeDepth() {
+ return treeDepth;
+ }
+
+ /**
+ * Determines if the tree is balanced according to BAP95, which means the tree
+ * is flat-enough with respect to the bounds. Note that this definition of
+ * balanced is one where sub-trees of balanced trees are not necessarily
+ * balanced.
+ *
+ * @return true if the tree is balanced
+ */
+ @Override
+ protected boolean isBalanced() {
+ return totalLength >= minLengthByDepth[treeDepth];
+ }
+
+ /**
+ * Takes a substring of this one. This involves recursive descent along the
+ * left and right edges of the substring, and referencing any wholly contained
+ * segments in between. Any leaf nodes entirely uninvolved in the substring
+ * will not be referenced by the substring.
+ *
+ * <p>Substrings of {@code length < 2} should result in at most a single
+ * recursive call chain, terminating at a leaf node. Thus the result will be a
+ * {@link com.google.protobuf.ByteString.LeafByteString}.
+ *
+ * @param beginIndex start at this index
+ * @param endIndex the last character is the one before this index
+ * @return substring leaf node or tree
+ */
+ @Override
+ public ByteString substring(int beginIndex, int endIndex) {
+ final int length = checkRange(beginIndex, endIndex, totalLength);
+
+ if (length == 0) {
+ // Empty substring
+ return ByteString.EMPTY;
+ }
+
+ if (length == totalLength) {
+ // The whole string
+ return this;
+ }
+
+ // Proper substring
+ if (endIndex <= leftLength) {
+ // Substring on the left
+ return left.substring(beginIndex, endIndex);
+ }
+
+ if (beginIndex >= leftLength) {
+ // Substring on the right
+ return right.substring(beginIndex - leftLength, endIndex - leftLength);
+ }
+
+ // Split substring
+ ByteString leftSub = left.substring(beginIndex);
+ ByteString rightSub = right.substring(0, endIndex - leftLength);
+ // Intentionally not rebalancing, since in many cases these two
+ // substrings will already be less deep than the top-level
+ // RopeByteString we're taking a substring of.
+ return new RopeByteString(leftSub, rightSub);
+ }
+
+ // =================================================================
+ // ByteString -> byte[]
+
+ @Override
+ protected void copyToInternal(byte[] target, int sourceOffset,
+ int targetOffset, int numberToCopy) {
+ if (sourceOffset + numberToCopy <= leftLength) {
+ left.copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
+ } else if (sourceOffset >= leftLength) {
+ right.copyToInternal(target, sourceOffset - leftLength, targetOffset,
+ numberToCopy);
+ } else {
+ int leftLength = this.leftLength - sourceOffset;
+ left.copyToInternal(target, sourceOffset, targetOffset, leftLength);
+ right.copyToInternal(target, 0, targetOffset + leftLength,
+ numberToCopy - leftLength);
+ }
+ }
+
+ @Override
+ public void copyTo(ByteBuffer target) {
+ left.copyTo(target);
+ right.copyTo(target);
+ }
+
+ @Override
+ public ByteBuffer asReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = ByteBuffer.wrap(toByteArray());
+ return byteBuffer.asReadOnlyBuffer();
+ }
+
+ @Override
+ public List<ByteBuffer> asReadOnlyByteBufferList() {
+ // Walk through the list of LeafByteString's that make up this
+ // rope, and add each one as a read-only ByteBuffer.
+ List<ByteBuffer> result = new ArrayList<ByteBuffer>();
+ PieceIterator pieces = new PieceIterator(this);
+ while (pieces.hasNext()) {
+ LeafByteString byteString = pieces.next();
+ result.add(byteString.asReadOnlyByteBuffer());
+ }
+ return result;
+ }
+
+ @Override
+ public void writeTo(OutputStream outputStream) throws IOException {
+ left.writeTo(outputStream);
+ right.writeTo(outputStream);
+ }
+
+ @Override
+ void writeToInternal(OutputStream out, int sourceOffset,
+ int numberToWrite) throws IOException {
+ if (sourceOffset + numberToWrite <= leftLength) {
+ left.writeToInternal(out, sourceOffset, numberToWrite);
+ } else if (sourceOffset >= leftLength) {
+ right.writeToInternal(out, sourceOffset - leftLength, numberToWrite);
+ } else {
+ int numberToWriteInLeft = leftLength - sourceOffset;
+ left.writeToInternal(out, sourceOffset, numberToWriteInLeft);
+ right.writeToInternal(out, 0, numberToWrite - numberToWriteInLeft);
+ }
+ }
+
+ @Override
+ void writeTo(ByteOutput output) throws IOException {
+ left.writeTo(output);
+ right.writeTo(output);
+ }
+
+
+ @Override
+ protected String toStringInternal(Charset charset) {
+ return new String(toByteArray(), charset);
+ }
+
+ // =================================================================
+ // UTF-8 decoding
+
+ @Override
+ public boolean isValidUtf8() {
+ int leftPartial = left.partialIsValidUtf8(Utf8.COMPLETE, 0, leftLength);
+ int state = right.partialIsValidUtf8(leftPartial, 0, right.size());
+ return state == Utf8.COMPLETE;
+ }
+
+ @Override
+ protected int partialIsValidUtf8(int state, int offset, int length) {
+ int toIndex = offset + length;
+ if (toIndex <= leftLength) {
+ return left.partialIsValidUtf8(state, offset, length);
+ } else if (offset >= leftLength) {
+ return right.partialIsValidUtf8(state, offset - leftLength, length);
+ } else {
+ int leftLength = this.leftLength - offset;
+ int leftPartial = left.partialIsValidUtf8(state, offset, leftLength);
+ return right.partialIsValidUtf8(leftPartial, 0, length - leftLength);
+ }
+ }
+
+ // =================================================================
+ // equals() and hashCode()
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof ByteString)) {
+ return false;
+ }
+
+ ByteString otherByteString = (ByteString) other;
+ if (totalLength != otherByteString.size()) {
+ return false;
+ }
+ if (totalLength == 0) {
+ return true;
+ }
+
+ // You don't really want to be calling equals on long strings, but since
+ // we cache the hashCode, we effectively cache inequality. We use the cached
+ // hashCode if it's already computed. It's arguable we should compute the
+ // hashCode here, and if we're going to be testing a bunch of byteStrings,
+ // it might even make sense.
+ int thisHash = peekCachedHashCode();
+ int thatHash = otherByteString.peekCachedHashCode();
+ if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
+ return false;
+ }
+
+ return equalsFragments(otherByteString);
+ }
+
+ /**
+ * Determines if this string is equal to another of the same length by
+ * iterating over the leaf nodes. On each step of the iteration, the
+ * overlapping segments of the leaves are compared.
+ *
+ * @param other string of the same length as this one
+ * @return true if the values of this string equals the value of the given
+ * one
+ */
+ private boolean equalsFragments(ByteString other) {
+ int thisOffset = 0;
+ Iterator<LeafByteString> thisIter = new PieceIterator(this);
+ LeafByteString thisString = thisIter.next();
+
+ int thatOffset = 0;
+ Iterator<LeafByteString> thatIter = new PieceIterator(other);
+ LeafByteString thatString = thatIter.next();
+
+ int pos = 0;
+ while (true) {
+ int thisRemaining = thisString.size() - thisOffset;
+ int thatRemaining = thatString.size() - thatOffset;
+ int bytesToCompare = Math.min(thisRemaining, thatRemaining);
+
+ // At least one of the offsets will be zero
+ boolean stillEqual = (thisOffset == 0)
+ ? thisString.equalsRange(thatString, thatOffset, bytesToCompare)
+ : thatString.equalsRange(thisString, thisOffset, bytesToCompare);
+ if (!stillEqual) {
+ return false;
+ }
+
+ pos += bytesToCompare;
+ if (pos >= totalLength) {
+ if (pos == totalLength) {
+ return true;
+ }
+ throw new IllegalStateException();
+ }
+ // We always get to the end of at least one of the pieces
+ if (bytesToCompare == thisRemaining) { // If reached end of this
+ thisOffset = 0;
+ thisString = thisIter.next();
+ } else {
+ thisOffset += bytesToCompare;
+ }
+ if (bytesToCompare == thatRemaining) { // If reached end of that
+ thatOffset = 0;
+ thatString = thatIter.next();
+ } else {
+ thatOffset += bytesToCompare;
+ }
+ }
+ }
+
+ @Override
+ protected int partialHash(int h, int offset, int length) {
+ int toIndex = offset + length;
+ if (toIndex <= leftLength) {
+ return left.partialHash(h, offset, length);
+ } else if (offset >= leftLength) {
+ return right.partialHash(h, offset - leftLength, length);
+ } else {
+ int leftLength = this.leftLength - offset;
+ int leftPartial = left.partialHash(h, offset, leftLength);
+ return right.partialHash(leftPartial, 0, length - leftLength);
+ }
+ }
+
+ // =================================================================
+ // Input stream
+
+ @Override
+ public CodedInputStream newCodedInput() {
+ return CodedInputStream.newInstance(new RopeInputStream());
+ }
+
+ @Override
+ public InputStream newInput() {
+ return new RopeInputStream();
+ }
+
+ /**
+ * This class implements the balancing algorithm of BAP95. In the paper the
+ * authors use an array to keep track of pieces, while here we use a stack.
+ * The tree is balanced by traversing subtrees in left to right order, and the
+ * stack always contains the part of the string we've traversed so far.
+ *
+ * <p>One surprising aspect of the algorithm is the result of balancing is not
+ * necessarily balanced, though it is nearly balanced. For details, see
+ * BAP95.
+ */
+ private static class Balancer {
+ // Stack containing the part of the string, starting from the left, that
+ // we've already traversed. The final string should be the equivalent of
+ // concatenating the strings on the stack from bottom to top.
+ private final Stack<ByteString> prefixesStack = new Stack<ByteString>();
+
+ private ByteString balance(ByteString left, ByteString right) {
+ doBalance(left);
+ doBalance(right);
+
+ // Sweep stack to gather the result
+ ByteString partialString = prefixesStack.pop();
+ while (!prefixesStack.isEmpty()) {
+ ByteString newLeft = prefixesStack.pop();
+ partialString = new RopeByteString(newLeft, partialString);
+ }
+ // We should end up with a RopeByteString since at a minimum we will
+ // create one from concatenating left and right
+ return partialString;
+ }
+
+ private void doBalance(ByteString root) {
+ // BAP95: Insert balanced subtrees whole. This means the result might not
+ // be balanced, leading to repeated rebalancings on concatenate. However,
+ // these rebalancings are shallow due to ignoring balanced subtrees, and
+ // relatively few calls to insert() result.
+ if (root.isBalanced()) {
+ insert(root);
+ } else if (root instanceof RopeByteString) {
+ RopeByteString rbs = (RopeByteString) root;
+ doBalance(rbs.left);
+ doBalance(rbs.right);
+ } else {
+ throw new IllegalArgumentException(
+ "Has a new type of ByteString been created? Found " +
+ root.getClass());
+ }
+ }
+
+ /**
+ * Push a string on the balance stack (BAP95). BAP95 uses an array and
+ * calls the elements in the array 'bins'. We instead use a stack, so the
+ * 'bins' of lengths are represented by differences between the elements of
+ * minLengthByDepth.
+ *
+ * <p>If the length bin for our string, and all shorter length bins, are
+ * empty, we just push it on the stack. Otherwise, we need to start
+ * concatenating, putting the given string in the "middle" and continuing
+ * until we land in an empty length bin that matches the length of our
+ * concatenation.
+ *
+ * @param byteString string to place on the balance stack
+ */
+ private void insert(ByteString byteString) {
+ int depthBin = getDepthBinForLength(byteString.size());
+ int binEnd = minLengthByDepth[depthBin + 1];
+
+ // BAP95: Concatenate all trees occupying bins representing the length of
+ // our new piece or of shorter pieces, to the extent that is possible.
+ // The goal is to clear the bin which our piece belongs in, but that may
+ // not be entirely possible if there aren't enough longer bins occupied.
+ if (prefixesStack.isEmpty() || prefixesStack.peek().size() >= binEnd) {
+ prefixesStack.push(byteString);
+ } else {
+ int binStart = minLengthByDepth[depthBin];
+
+ // Concatenate the subtrees of shorter length
+ ByteString newTree = prefixesStack.pop();
+ while (!prefixesStack.isEmpty()
+ && prefixesStack.peek().size() < binStart) {
+ ByteString left = prefixesStack.pop();
+ newTree = new RopeByteString(left, newTree);
+ }
+
+ // Concatenate the given string
+ newTree = new RopeByteString(newTree, byteString);
+
+ // Continue concatenating until we land in an empty bin
+ while (!prefixesStack.isEmpty()) {
+ depthBin = getDepthBinForLength(newTree.size());
+ binEnd = minLengthByDepth[depthBin + 1];
+ if (prefixesStack.peek().size() < binEnd) {
+ ByteString left = prefixesStack.pop();
+ newTree = new RopeByteString(left, newTree);
+ } else {
+ break;
+ }
+ }
+ prefixesStack.push(newTree);
+ }
+ }
+
+ private int getDepthBinForLength(int length) {
+ int depth = Arrays.binarySearch(minLengthByDepth, length);
+ if (depth < 0) {
+ // It wasn't an exact match, so convert to the index of the containing
+ // fragment, which is one less even than the insertion point.
+ int insertionPoint = -(depth + 1);
+ depth = insertionPoint - 1;
+ }
+
+ return depth;
+ }
+ }
+
+ /**
+ * This class is a continuable tree traversal, which keeps the state
+ * information which would exist on the stack in a recursive traversal instead
+ * on a stack of "Bread Crumbs". The maximum depth of the stack in this
+ * iterator is the same as the depth of the tree being traversed.
+ *
+ * <p>This iterator is used to implement
+ * {@link RopeByteString#equalsFragments(ByteString)}.
+ */
+ private static class PieceIterator implements Iterator<LeafByteString> {
+
+ private final Stack<RopeByteString> breadCrumbs =
+ new Stack<RopeByteString>();
+ private LeafByteString next;
+
+ private PieceIterator(ByteString root) {
+ next = getLeafByLeft(root);
+ }
+
+ private LeafByteString getLeafByLeft(ByteString root) {
+ ByteString pos = root;
+ while (pos instanceof RopeByteString) {
+ RopeByteString rbs = (RopeByteString) pos;
+ breadCrumbs.push(rbs);
+ pos = rbs.left;
+ }
+ return (LeafByteString) pos;
+ }
+
+ private LeafByteString getNextNonEmptyLeaf() {
+ while (true) {
+ // Almost always, we go through this loop exactly once. However, if
+ // we discover an empty string in the rope, we toss it and try again.
+ if (breadCrumbs.isEmpty()) {
+ return null;
+ } else {
+ LeafByteString result = getLeafByLeft(breadCrumbs.pop().right);
+ if (!result.isEmpty()) {
+ return result;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ /**
+ * Returns the next item and advances one
+ * {@link com.google.protobuf.ByteString.LeafByteString}.
+ *
+ * @return next non-empty LeafByteString or {@code null}
+ */
+ @Override
+ public LeafByteString next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ LeafByteString result = next;
+ next = getNextNonEmptyLeaf();
+ return result;
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ // =================================================================
+ // 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(
+ "RopeByteStream instances are not to be serialized directly");
+ }
+
+ /**
+ * This class is the {@link RopeByteString} equivalent for
+ * {@link ByteArrayInputStream}.
+ */
+ private class RopeInputStream extends InputStream {
+ // Iterates through the pieces of the rope
+ private PieceIterator pieceIterator;
+ // The current piece
+ private LeafByteString currentPiece;
+ // The size of the current piece
+ private int currentPieceSize;
+ // The index of the next byte to read in the current piece
+ private int currentPieceIndex;
+ // The offset of the start of the current piece in the rope byte string
+ private int currentPieceOffsetInRope;
+ // Offset in the buffer at which user called mark();
+ private int mark;
+
+ public RopeInputStream() {
+ initialize();
+ }
+
+ @Override
+ public int read(byte b[], int offset, int length) {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (offset < 0 || length < 0 || length > b.length - offset) {
+ throw new IndexOutOfBoundsException();
+ }
+ return readSkipInternal(b, offset, length);
+ }
+
+ @Override
+ public long skip(long length) {
+ if (length < 0) {
+ throw new IndexOutOfBoundsException();
+ } else if (length > Integer.MAX_VALUE) {
+ length = Integer.MAX_VALUE;
+ }
+ return readSkipInternal(null, 0, (int) length);
+ }
+
+ /**
+ * Internal implementation of read and skip. If b != null, then read the
+ * next {@code length} bytes into the buffer {@code b} at
+ * offset {@code offset}. If b == null, then skip the next {@code length}
+ * bytes.
+ * <p>
+ * This method assumes that all error checking has already happened.
+ * <p>
+ * Returns the actual number of bytes read or skipped.
+ */
+ private int readSkipInternal(byte b[], int offset, int length) {
+ int bytesRemaining = length;
+ while (bytesRemaining > 0) {
+ advanceIfCurrentPieceFullyRead();
+ if (currentPiece == null) {
+ if (bytesRemaining == length) {
+ // We didn't manage to read anything
+ return -1;
+ }
+ break;
+ } else {
+ // Copy the bytes from this piece.
+ int currentPieceRemaining = currentPieceSize - currentPieceIndex;
+ int count = Math.min(currentPieceRemaining, bytesRemaining);
+ if (b != null) {
+ currentPiece.copyTo(b, currentPieceIndex, offset, count);
+ offset += count;
+ }
+ currentPieceIndex += count;
+ bytesRemaining -= count;
+ }
+ }
+ // Return the number of bytes read.
+ return length - bytesRemaining;
+ }
+
+ @Override
+ public int read() throws IOException {
+ advanceIfCurrentPieceFullyRead();
+ if (currentPiece == null) {
+ return -1;
+ } else {
+ return currentPiece.byteAt(currentPieceIndex++) & 0xFF;
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ int bytesRead = currentPieceOffsetInRope + currentPieceIndex;
+ return RopeByteString.this.size() - bytesRead;
+ }
+
+ @Override
+ public boolean markSupported() {
+ return true;
+ }
+
+ @Override
+ public void mark(int readAheadLimit) {
+ // Set the mark to our position in the byte string
+ mark = currentPieceOffsetInRope + currentPieceIndex;
+ }
+
+ @Override
+ public synchronized void reset() {
+ // Just reinitialize and skip the specified number of bytes.
+ initialize();
+ readSkipInternal(null, 0, mark);
+ }
+
+ /** Common initialization code used by both the constructor and reset() */
+ private void initialize() {
+ pieceIterator = new PieceIterator(RopeByteString.this);
+ currentPiece = pieceIterator.next();
+ currentPieceSize = currentPiece.size();
+ currentPieceIndex = 0;
+ currentPieceOffsetInRope = 0;
+ }
+
+ /**
+ * Skips to the next piece if we have read all the data in the current
+ * piece. Sets currentPiece to null if we have reached the end of the
+ * input.
+ */
+ private void advanceIfCurrentPieceFullyRead() {
+ if (currentPiece != null && currentPieceIndex == currentPieceSize) {
+ // Generally, we can only go through this loop at most once, since
+ // empty strings can't end up in a rope. But better to test.
+ currentPieceOffsetInRope += currentPieceSize;
+ currentPieceIndex = 0;
+ if (pieceIterator.hasNext()) {
+ currentPiece = pieceIterator.next();
+ currentPieceSize = currentPiece.size();
+ } else {
+ currentPiece = null;
+ currentPieceSize = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcCallback.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcCallback.java
new file mode 100644
index 0000000000..10752968e2
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcCallback.java
@@ -0,0 +1,47 @@
+// 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;
+
+/**
+ * Interface for an RPC callback, normally called when an RPC completes.
+ * {@code ParameterType} is normally the method's response message type.
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation. This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcCallback<ParameterType> {
+ void run(ParameterType parameter);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcChannel.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcChannel.java
new file mode 100644
index 0000000000..f272f4ad72
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcChannel.java
@@ -0,0 +1,71 @@
+// 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;
+
+/**
+ * <p>Abstract interface for an RPC channel. An {@code RpcChannel} represents a
+ * communication line to a {@link Service} which can be used to call that
+ * {@link Service}'s methods. The {@link Service} may be running on another
+ * machine. Normally, you should not call an {@code RpcChannel} directly, but
+ * instead construct a stub {@link Service} wrapping it. Example:
+ *
+ * <pre>
+ * RpcChannel channel = rpcImpl.newChannel("remotehost.example.com:1234");
+ * RpcController controller = rpcImpl.newController();
+ * MyService service = MyService.newStub(channel);
+ * service.myMethod(controller, request, callback);
+ * </pre>
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation. This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcChannel {
+ /**
+ * Call the given method of the remote service. This method is similar to
+ * {@code Service.callMethod()} with one important difference: the caller
+ * decides the types of the {@code Message} objects, not the callee. The
+ * request may be of any type as long as
+ * {@code request.getDescriptor() == method.getInputType()}.
+ * The response passed to the callback will be of the same type as
+ * {@code responsePrototype} (which must have
+ * {@code getDescriptor() == method.getOutputType()}).
+ */
+ void callMethod(Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request,
+ Message responsePrototype,
+ RpcCallback<Message> done);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcController.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcController.java
new file mode 100644
index 0000000000..a92dd7be6d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcController.java
@@ -0,0 +1,118 @@
+// 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;
+
+/**
+ * <p>An {@code RpcController} mediates a single method call. The primary
+ * purpose of the controller is to provide a way to manipulate settings
+ * specific to the RPC implementation and to find out about RPC-level errors.
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation. This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * <p>The methods provided by the {@code RpcController} interface are intended
+ * to be a "least common denominator" set of features which we expect all
+ * implementations to support. Specific implementations may provide more
+ * advanced features (e.g. deadline propagation).
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface RpcController {
+ // -----------------------------------------------------------------
+ // These calls may be made from the client side only. Their results
+ // are undefined on the server side (may throw RuntimeExceptions).
+
+ /**
+ * Resets the RpcController to its initial state so that it may be reused in
+ * a new call. This can be called from the client side only. It must not
+ * be called while an RPC is in progress.
+ */
+ void reset();
+
+ /**
+ * After a call has finished, returns true if the call failed. The possible
+ * reasons for failure depend on the RPC implementation. {@code failed()}
+ * most only be called on the client side, and must not be called before a
+ * call has finished.
+ */
+ boolean failed();
+
+ /**
+ * If {@code failed()} is {@code true}, returns a human-readable description
+ * of the error.
+ */
+ String errorText();
+
+ /**
+ * Advises the RPC system that the caller desires that the RPC call be
+ * canceled. The RPC system may cancel it immediately, may wait awhile and
+ * then cancel it, or may not even cancel the call at all. If the call is
+ * canceled, the "done" callback will still be called and the RpcController
+ * will indicate that the call failed at that time.
+ */
+ void startCancel();
+
+ // -----------------------------------------------------------------
+ // These calls may be made from the server side only. Their results
+ // are undefined on the client side (may throw RuntimeExceptions).
+
+ /**
+ * Causes {@code failed()} to return true on the client side. {@code reason}
+ * will be incorporated into the message returned by {@code errorText()}.
+ * If you find you need to return machine-readable information about
+ * failures, you should incorporate it into your response protocol buffer
+ * and should NOT call {@code setFailed()}.
+ */
+ void setFailed(String reason);
+
+ /**
+ * If {@code true}, indicates that the client canceled the RPC, so the server
+ * may as well give up on replying to it. This method must be called on the
+ * server side only. The server should still call the final "done" callback.
+ */
+ boolean isCanceled();
+
+ /**
+ * Asks that the given callback be called when the RPC is canceled. The
+ * parameter passed to the callback will always be {@code null}. The
+ * callback will always be called exactly once. If the RPC completes without
+ * being canceled, the callback will be called after completion. If the RPC
+ * has already been canceled when NotifyOnCancel() is called, the callback
+ * will be called immediately.
+ *
+ * <p>{@code notifyOnCancel()} must be called no more than once per request.
+ * It must be called on the server side only.
+ */
+ void notifyOnCancel(RpcCallback<Object> callback);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcUtil.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcUtil.java
new file mode 100644
index 0000000000..f7d555ae15
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/RpcUtil.java
@@ -0,0 +1,136 @@
+// 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;
+
+/**
+ * Grab-bag of utility functions useful when dealing with RPCs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class RpcUtil {
+ private RpcUtil() {}
+
+ /**
+ * Take an {@code RpcCallback<Message>} and convert it to an
+ * {@code RpcCallback} accepting a specific message type. This is always
+ * type-safe (parameter type contravariance).
+ */
+ @SuppressWarnings("unchecked")
+ public static <Type extends Message> RpcCallback<Type>
+ specializeCallback(final RpcCallback<Message> originalCallback) {
+ return (RpcCallback<Type>)originalCallback;
+ // The above cast works, but only due to technical details of the Java
+ // implementation. A more theoretically correct -- but less efficient --
+ // implementation would be as follows:
+ // return new RpcCallback<Type>() {
+ // public void run(Type parameter) {
+ // originalCallback.run(parameter);
+ // }
+ // };
+ }
+
+ /**
+ * Take an {@code RpcCallback} accepting a specific message type and convert
+ * it to an {@code RpcCallback<Message>}. The generalized callback will
+ * accept any message object which has the same descriptor, and will convert
+ * it to the correct class before calling the original callback. However,
+ * if the generalized callback is given a message with a different descriptor,
+ * an exception will be thrown.
+ */
+ public static <Type extends Message>
+ RpcCallback<Message> generalizeCallback(
+ final RpcCallback<Type> originalCallback,
+ final Class<Type> originalClass,
+ final Type defaultInstance) {
+ return new RpcCallback<Message>() {
+ @Override
+ public void run(final Message parameter) {
+ Type typedParameter;
+ try {
+ typedParameter = originalClass.cast(parameter);
+ } catch (ClassCastException ignored) {
+ typedParameter = copyAsType(defaultInstance, parameter);
+ }
+ originalCallback.run(typedParameter);
+ }
+ };
+ }
+
+ /**
+ * Creates a new message of type "Type" which is a copy of "source". "source"
+ * must have the same descriptor but may be a different class (e.g.
+ * DynamicMessage).
+ */
+ @SuppressWarnings("unchecked")
+ private static <Type extends Message> Type copyAsType(
+ final Type typeDefaultInstance, final Message source) {
+ return (Type) typeDefaultInstance
+ .newBuilderForType().mergeFrom(source).build();
+ }
+
+ /**
+ * Creates a callback which can only be called once. This may be useful for
+ * security, when passing a callback to untrusted code: most callbacks do
+ * not expect to be called more than once, so doing so may expose bugs if it
+ * is not prevented.
+ */
+ public static <ParameterType>
+ RpcCallback<ParameterType> newOneTimeCallback(
+ final RpcCallback<ParameterType> originalCallback) {
+ return new RpcCallback<ParameterType>() {
+ private boolean alreadyCalled = false;
+
+ @Override
+ public void run(final ParameterType parameter) {
+ synchronized (this) {
+ if (alreadyCalled) {
+ throw new AlreadyCalledException();
+ }
+ alreadyCalled = true;
+ }
+
+ originalCallback.run(parameter);
+ }
+ };
+ }
+
+ /**
+ * Exception thrown when a one-time callback is called more than once.
+ */
+ public static final class AlreadyCalledException extends RuntimeException {
+ private static final long serialVersionUID = 5469741279507848266L;
+
+ public AlreadyCalledException() {
+ super("This RpcCallback was already called and cannot be called " +
+ "multiple times.");
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Service.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Service.java
new file mode 100644
index 0000000000..ba7b033ed4
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Service.java
@@ -0,0 +1,117 @@
+// 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;
+
+/**
+ * Abstract base interface for protocol-buffer-based RPC services. Services
+ * themselves are abstract classes (implemented either by servers or as
+ * stubs), but they subclass this base interface. The methods of this
+ * interface can be used to call the methods of the service without knowing
+ * its exact type at compile time (analogous to the Message interface).
+ *
+ * <p>Starting with version 2.3.0, RPC implementations should not try to build
+ * on this, but should instead provide code generator plugins which generate
+ * code specific to the particular RPC implementation. This way the generated
+ * code can be more appropriate for the implementation in use and can avoid
+ * unnecessary layers of indirection.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public interface Service {
+ /**
+ * Get the {@code ServiceDescriptor} describing this service and its methods.
+ */
+ Descriptors.ServiceDescriptor getDescriptorForType();
+
+ /**
+ * <p>Call a method of the service specified by MethodDescriptor. This is
+ * normally implemented as a simple {@code switch()} that calls the standard
+ * definitions of the service's methods.
+ *
+ * <p>Preconditions:
+ * <ul>
+ * <li>{@code method.getService() == getDescriptorForType()}
+ * <li>{@code request} is of the exact same class as the object returned by
+ * {@code getRequestPrototype(method)}.
+ * <li>{@code controller} is of the correct type for the RPC implementation
+ * being used by this Service. For stubs, the "correct type" depends
+ * on the RpcChannel which the stub is using. Server-side Service
+ * implementations are expected to accept whatever type of
+ * {@code RpcController} the server-side RPC implementation uses.
+ * </ul>
+ *
+ * <p>Postconditions:
+ * <ul>
+ * <li>{@code done} will be called when the method is complete. This may be
+ * before {@code callMethod()} returns or it may be at some point in
+ * the future.
+ * <li>The parameter to {@code done} is the response. It must be of the
+ * exact same type as would be returned by
+ * {@code getResponsePrototype(method)}.
+ * <li>If the RPC failed, the parameter to {@code done} will be
+ * {@code null}. Further details about the failure can be found by
+ * querying {@code controller}.
+ * </ul>
+ */
+ void callMethod(Descriptors.MethodDescriptor method,
+ RpcController controller,
+ Message request,
+ RpcCallback<Message> done);
+
+ /**
+ * <p>{@code callMethod()} requires that the request passed in is of a
+ * particular subclass of {@code Message}. {@code getRequestPrototype()}
+ * gets the default instances of this type for a given method. You can then
+ * call {@code Message.newBuilderForType()} on this instance to
+ * construct a builder to build an object which you can then pass to
+ * {@code callMethod()}.
+ *
+ * <p>Example:
+ * <pre>
+ * MethodDescriptor method =
+ * service.getDescriptorForType().findMethodByName("Foo");
+ * Message request =
+ * stub.getRequestPrototype(method).newBuilderForType()
+ * .mergeFrom(input).build();
+ * service.callMethod(method, request, callback);
+ * </pre>
+ */
+ Message getRequestPrototype(Descriptors.MethodDescriptor method);
+
+ /**
+ * Like {@code getRequestPrototype()}, but gets a prototype of the response
+ * message. {@code getResponsePrototype()} is generally not needed because
+ * the {@code Service} implementation constructs the response message itself,
+ * but it may be useful in some cases to know ahead of time what type of
+ * object will be returned.
+ */
+ Message getResponsePrototype(Descriptors.MethodDescriptor method);
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ServiceException.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ServiceException.java
new file mode 100644
index 0000000000..00d5707523
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/ServiceException.java
@@ -0,0 +1,52 @@
+// 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;
+
+/**
+ * Thrown by blocking RPC methods when a failure occurs.
+ *
+ * @author cpovirk@google.com (Chris Povirk)
+ */
+public class ServiceException extends Exception {
+ private static final long serialVersionUID = -1219262335729891920L;
+
+ public ServiceException(final String message) {
+ super(message);
+ }
+
+ public ServiceException(final Throwable cause) {
+ super(cause);
+ }
+
+ public ServiceException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
new file mode 100644
index 0000000000..941b5defc9
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -0,0 +1,241 @@
+// 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;
+
+/**
+ * {@code SingleFieldBuilder} implements a structure that a protocol
+ * message uses to hold a single field of another protocol message. It supports
+ * the classical use case of setting an immutable {@link Message} as the value
+ * of the field and is highly optimized around this.
+ * <br>
+ * It also supports the additional use case of setting a {@link Message.Builder}
+ * as the field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilder
+ <MType extends GeneratedMessage,
+ BType extends GeneratedMessage.Builder,
+ IType extends MessageOrBuilder>
+ implements GeneratedMessage.BuilderParent {
+
+ // Parent to send changes to.
+ private GeneratedMessage.BuilderParent parent;
+
+ // Invariant: one of builder or message fields must be non-null.
+
+ // If set, this is the case where we are backed by a builder. In this case,
+ // message field represents a cached message for the builder (or null if
+ // there is no cached message).
+ private BType builder;
+
+ // If builder is non-null, this represents a cached message from the builder.
+ // If builder is null, this is the authoritative message for the field.
+ private MType message;
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
+ private boolean isClean;
+
+ public SingleFieldBuilder(
+ MType message,
+ GeneratedMessage.BuilderParent parent,
+ boolean isClean) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ this.message = message;
+ this.parent = parent;
+ this.isClean = isClean;
+ }
+
+ public void dispose() {
+ // Null out parent so we stop sending it invalidations.
+ parent = null;
+ }
+
+ /**
+ * Get the message for the field. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it. If no message has
+ * been set, returns the default instance of the message.
+ *
+ * @return the message for the field
+ */
+ @SuppressWarnings("unchecked")
+ public MType getMessage() {
+ if (message == null) {
+ // If message is null, the invariant is that we must be have a builder.
+ message = (MType) builder.buildPartial();
+ }
+ return message;
+ }
+
+ /**
+ * Builds the message and returns it.
+ *
+ * @return the message
+ */
+ public MType build() {
+ // Now that build has been called, we are required to dispatch
+ // invalidations.
+ isClean = true;
+ return getMessage();
+ }
+
+ /**
+ * Gets a builder for the field. If no builder has been created yet, a
+ * builder is created on demand by calling {@link Message#toBuilder}.
+ *
+ * @return The builder for the field
+ */
+ @SuppressWarnings("unchecked")
+ public BType getBuilder() {
+ if (builder == null) {
+ // builder.mergeFrom() on a fresh builder
+ // does not create any sub-objects with independent clean/dirty states,
+ // therefore setting the builder itself to clean without actually calling
+ // build() cannot break any invariants.
+ builder = (BType) message.newBuilderForType(this);
+ builder.mergeFrom(message); // no-op if message is the default message
+ builder.markClean();
+ }
+ return builder;
+ }
+
+ /**
+ * Gets the base class interface for the field. This may either be a builder
+ * or a message. It will return whatever is more efficient.
+ *
+ * @return the message or builder for the field as the base class interface
+ */
+ @SuppressWarnings("unchecked")
+ public IType getMessageOrBuilder() {
+ if (builder != null) {
+ return (IType) builder;
+ } else {
+ return (IType) message;
+ }
+ }
+
+ /**
+ * Sets a message for the field replacing any existing value.
+ *
+ * @param message the message to set
+ * @return the builder
+ */
+ public SingleFieldBuilder<MType, BType, IType> setMessage(
+ MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ this.message = message;
+ if (builder != null) {
+ builder.dispose();
+ builder = null;
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Merges the field from another field.
+ *
+ * @param value the value to merge from
+ * @return the builder
+ */
+ public SingleFieldBuilder<MType, BType, IType> mergeFrom(
+ MType value) {
+ if (builder == null && message == message.getDefaultInstanceForType()) {
+ message = value;
+ } else {
+ getBuilder().mergeFrom(value);
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Clears the value of the field.
+ *
+ * @return the builder
+ */
+ @SuppressWarnings("unchecked")
+ public SingleFieldBuilder<MType, BType, IType> clear() {
+ message = (MType) (message != null ?
+ message.getDefaultInstanceForType() :
+ builder.getDefaultInstanceForType());
+ if (builder != null) {
+ builder.dispose();
+ builder = null;
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ private void onChanged() {
+ // If builder is null, this is the case where onChanged is being called
+ // from setMessage or clear.
+ if (builder != null) {
+ message = null;
+ }
+ if (isClean && parent != null) {
+ parent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java
new file mode 100644
index 0000000000..fb1f76a731
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java
@@ -0,0 +1,241 @@
+// 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;
+
+/**
+ * {@code SingleFieldBuilderV3} implements a structure that a protocol
+ * message uses to hold a single field of another protocol message. It supports
+ * the classical use case of setting an immutable {@link Message} as the value
+ * of the field and is highly optimized around this.
+ * <br>
+ * It also supports the additional use case of setting a {@link Message.Builder}
+ * as the field and deferring conversion of that {@code Builder}
+ * to an immutable {@code Message}. In this way, it's possible to maintain
+ * a tree of {@code Builder}'s that acts as a fully read/write data
+ * structure.
+ * <br>
+ * Logically, one can think of a tree of builders as converting the entire tree
+ * to messages when build is called on the root or when any method is called
+ * that desires a Message instead of a Builder. In terms of the implementation,
+ * the {@code SingleFieldBuilderV3} and {@code RepeatedFieldBuilderV3}
+ * classes cache messages that were created so that messages only need to be
+ * created when some change occurred in its builder or a builder for one of its
+ * descendants.
+ *
+ * @param <MType> the type of message for the field
+ * @param <BType> the type of builder for the field
+ * @param <IType> the common interface for the message and the builder
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilderV3
+ <MType extends AbstractMessage,
+ BType extends AbstractMessage.Builder,
+ IType extends MessageOrBuilder>
+ implements AbstractMessage.BuilderParent {
+
+ // Parent to send changes to.
+ private AbstractMessage.BuilderParent parent;
+
+ // Invariant: one of builder or message fields must be non-null.
+
+ // If set, this is the case where we are backed by a builder. In this case,
+ // message field represents a cached message for the builder (or null if
+ // there is no cached message).
+ private BType builder;
+
+ // If builder is non-null, this represents a cached message from the builder.
+ // If builder is null, this is the authoritative message for the field.
+ private MType message;
+
+ // Indicates that we've built a message and so we are now obligated
+ // to dispatch dirty invalidations. See AbstractMessage.BuilderListener.
+ private boolean isClean;
+
+ public SingleFieldBuilderV3(
+ MType message,
+ AbstractMessage.BuilderParent parent,
+ boolean isClean) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ this.message = message;
+ this.parent = parent;
+ this.isClean = isClean;
+ }
+
+ public void dispose() {
+ // Null out parent so we stop sending it invalidations.
+ parent = null;
+ }
+
+ /**
+ * Get the message for the field. If the message is currently stored
+ * as a {@code Builder}, it is converted to a {@code Message} by
+ * calling {@link Message.Builder#buildPartial} on it. If no message has
+ * been set, returns the default instance of the message.
+ *
+ * @return the message for the field
+ */
+ @SuppressWarnings("unchecked")
+ public MType getMessage() {
+ if (message == null) {
+ // If message is null, the invariant is that we must be have a builder.
+ message = (MType) builder.buildPartial();
+ }
+ return message;
+ }
+
+ /**
+ * Builds the message and returns it.
+ *
+ * @return the message
+ */
+ public MType build() {
+ // Now that build has been called, we are required to dispatch
+ // invalidations.
+ isClean = true;
+ return getMessage();
+ }
+
+ /**
+ * Gets a builder for the field. If no builder has been created yet, a
+ * builder is created on demand by calling {@link Message#toBuilder}.
+ *
+ * @return The builder for the field
+ */
+ @SuppressWarnings("unchecked")
+ public BType getBuilder() {
+ if (builder == null) {
+ // builder.mergeFrom() on a fresh builder
+ // does not create any sub-objects with independent clean/dirty states,
+ // therefore setting the builder itself to clean without actually calling
+ // build() cannot break any invariants.
+ builder = (BType) message.newBuilderForType(this);
+ builder.mergeFrom(message); // no-op if message is the default message
+ builder.markClean();
+ }
+ return builder;
+ }
+
+ /**
+ * Gets the base class interface for the field. This may either be a builder
+ * or a message. It will return whatever is more efficient.
+ *
+ * @return the message or builder for the field as the base class interface
+ */
+ @SuppressWarnings("unchecked")
+ public IType getMessageOrBuilder() {
+ if (builder != null) {
+ return (IType) builder;
+ } else {
+ return (IType) message;
+ }
+ }
+
+ /**
+ * Sets a message for the field replacing any existing value.
+ *
+ * @param message the message to set
+ * @return the builder
+ */
+ public SingleFieldBuilderV3<MType, BType, IType> setMessage(
+ MType message) {
+ if (message == null) {
+ throw new NullPointerException();
+ }
+ this.message = message;
+ if (builder != null) {
+ builder.dispose();
+ builder = null;
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Merges the field from another field.
+ *
+ * @param value the value to merge from
+ * @return the builder
+ */
+ public SingleFieldBuilderV3<MType, BType, IType> mergeFrom(
+ MType value) {
+ if (builder == null && message == message.getDefaultInstanceForType()) {
+ message = value;
+ } else {
+ getBuilder().mergeFrom(value);
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Clears the value of the field.
+ *
+ * @return the builder
+ */
+ @SuppressWarnings("unchecked")
+ public SingleFieldBuilderV3<MType, BType, IType> clear() {
+ message = (MType) (message != null ?
+ message.getDefaultInstanceForType() :
+ builder.getDefaultInstanceForType());
+ if (builder != null) {
+ builder.dispose();
+ builder = null;
+ }
+ onChanged();
+ return this;
+ }
+
+ /**
+ * Called when a the builder or one of its nested children has changed
+ * and any parent should be notified of its invalidation.
+ */
+ private void onChanged() {
+ // If builder is null, this is the case where onChanged is being called
+ // from setMessage or clear.
+ if (builder != null) {
+ message = null;
+ }
+ if (isClean && parent != null) {
+ parent.markDirty();
+
+ // Don't keep dispatching invalidations until build is called again.
+ isClean = false;
+ }
+ }
+
+ @Override
+ public void markDirty() {
+ onChanged();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
new file mode 100644
index 0000000000..66033f58e5
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -0,0 +1,673 @@
+// 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.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * A custom map implementation from FieldDescriptor to Object optimized to
+ * minimize the number of memory allocations for instances with a small number
+ * of mappings. The implementation stores the first {@code k} mappings in an
+ * array for a configurable value of {@code k}, allowing direct access to the
+ * corresponding {@code Entry}s without the need to create an Iterator. The
+ * remaining entries are stored in an overflow map. Iteration over the entries
+ * in the map should be done as follows:
+ *
+ * <pre> {@code
+ * for (int i = 0; i < fieldMap.getNumArrayEntries(); i++) {
+ * process(fieldMap.getArrayEntryAt(i));
+ * }
+ * for (Map.Entry<K, V> entry : fieldMap.getOverflowEntries()) {
+ * process(entry);
+ * }
+ * }</pre>
+ *
+ * The resulting iteration is in order of ascending field tag number. The
+ * object returned by {@link #entrySet()} adheres to the same contract but is
+ * less efficient as it necessarily involves creating an object for iteration.
+ * <p>
+ * The tradeoff for this memory efficiency is that the worst case running time
+ * of the {@code put()} operation is {@code O(k + lg n)}, which happens when
+ * entries are added in descending order. {@code k} should be chosen such that
+ * it covers enough common cases without adversely affecting larger maps. In
+ * practice, the worst case scenario does not happen for extensions because
+ * extension fields are serialized and deserialized in order of ascending tag
+ * number, but the worst case scenario can happen for DynamicMessages.
+ * <p>
+ * The running time for all other operations is similar to that of
+ * {@code TreeMap}.
+ * <p>
+ * Instances are not thread-safe until {@link #makeImmutable()} is called,
+ * after which any modifying operation will result in an
+ * {@link UnsupportedOperationException}.
+ *
+ * @author darick@google.com Darick Tong
+ */
+// This class is final for all intents and purposes because the constructor is
+// private. However, the FieldDescriptor-specific logic is encapsulated in
+// a subclass to aid testability of the core logic.
+class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
+
+ /**
+ * Creates a new instance for mapping FieldDescriptors to their values.
+ * The {@link #makeImmutable()} implementation will convert the List values
+ * of any repeated fields to unmodifiable lists.
+ *
+ * @param arraySize The size of the entry array containing the
+ * lexicographically smallest mappings.
+ */
+ static <FieldDescriptorType extends
+ FieldSet.FieldDescriptorLite<FieldDescriptorType>>
+ SmallSortedMap<FieldDescriptorType, Object> newFieldMap(int arraySize) {
+ return new SmallSortedMap<FieldDescriptorType, Object>(arraySize) {
+ @Override
+ @SuppressWarnings("unchecked")
+ public void makeImmutable() {
+ if (!isImmutable()) {
+ for (int i = 0; i < getNumArrayEntries(); i++) {
+ final Map.Entry<FieldDescriptorType, Object> entry =
+ getArrayEntryAt(i);
+ if (entry.getKey().isRepeated()) {
+ final List value = (List) entry.getValue();
+ entry.setValue(Collections.unmodifiableList(value));
+ }
+ }
+ for (Map.Entry<FieldDescriptorType, Object> entry :
+ getOverflowEntries()) {
+ if (entry.getKey().isRepeated()) {
+ final List value = (List) entry.getValue();
+ entry.setValue(Collections.unmodifiableList(value));
+ }
+ }
+ }
+ super.makeImmutable();
+ }
+ };
+ }
+
+ /**
+ * Creates a new instance for testing.
+ *
+ * @param arraySize The size of the entry array containing the
+ * lexicographically smallest mappings.
+ */
+ static <K extends Comparable<K>, V> SmallSortedMap<K, V> newInstanceForTest(
+ int arraySize) {
+ return new SmallSortedMap<K, V>(arraySize);
+ }
+
+ private final int maxArraySize;
+ // The "entry array" is actually a List because generic arrays are not
+ // allowed. ArrayList also nicely handles the entry shifting on inserts and
+ // removes.
+ private List<Entry> entryList;
+ private Map<K, V> overflowEntries;
+ private boolean isImmutable;
+ // The EntrySet is a stateless view of the Map. It's initialized the first
+ // time it is requested and reused henceforth.
+ private volatile EntrySet lazyEntrySet;
+
+ /**
+ * @code arraySize Size of the array in which the lexicographically smallest
+ * mappings are stored. (i.e. the {@code k} referred to in the class
+ * documentation).
+ */
+ private SmallSortedMap(int arraySize) {
+ this.maxArraySize = arraySize;
+ this.entryList = Collections.emptyList();
+ this.overflowEntries = Collections.emptyMap();
+ }
+
+ /** Make this map immutable from this point forward. */
+ public void makeImmutable() {
+ if (!isImmutable) {
+ // Note: There's no need to wrap the entryList in an unmodifiableList
+ // because none of the list's accessors are exposed. The iterator() of
+ // overflowEntries, on the other hand, is exposed so it must be made
+ // unmodifiable.
+ overflowEntries = overflowEntries.isEmpty() ?
+ Collections.<K, V>emptyMap() :
+ Collections.unmodifiableMap(overflowEntries);
+ isImmutable = true;
+ }
+ }
+
+ /** @return Whether {@link #makeImmutable()} has been called. */
+ public boolean isImmutable() {
+ return isImmutable;
+ }
+
+ /** @return The number of entries in the entry array. */
+ public int getNumArrayEntries() {
+ return entryList.size();
+ }
+
+ /** @return The array entry at the given {@code index}. */
+ public Map.Entry<K, V> getArrayEntryAt(int index) {
+ return entryList.get(index);
+ }
+
+ /** @return There number of overflow entries. */
+ public int getNumOverflowEntries() {
+ return overflowEntries.size();
+ }
+
+ /** @return An iterable over the overflow entries. */
+ public Iterable<Map.Entry<K, V>> getOverflowEntries() {
+ return overflowEntries.isEmpty() ?
+ EmptySet.<Map.Entry<K, V>>iterable() :
+ overflowEntries.entrySet();
+ }
+
+
+ @Override
+ public int size() {
+ return entryList.size() + overflowEntries.size();
+ }
+
+ /**
+ * The implementation throws a {@code ClassCastException} if o is not an
+ * object of type {@code K}.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean containsKey(Object o) {
+ @SuppressWarnings("unchecked")
+ final K key = (K) o;
+ return binarySearchInArray(key) >= 0 || overflowEntries.containsKey(key);
+ }
+
+ /**
+ * The implementation throws a {@code ClassCastException} if o is not an
+ * object of type {@code K}.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public V get(Object o) {
+ @SuppressWarnings("unchecked")
+ final K key = (K) o;
+ final int index = binarySearchInArray(key);
+ if (index >= 0) {
+ return entryList.get(index).getValue();
+ }
+ return overflowEntries.get(key);
+ }
+
+ @Override
+ public V put(K key, V value) {
+ checkMutable();
+ final int index = binarySearchInArray(key);
+ if (index >= 0) {
+ // Replace existing array entry.
+ return entryList.get(index).setValue(value);
+ }
+ ensureEntryArrayMutable();
+ final int insertionPoint = -(index + 1);
+ if (insertionPoint >= maxArraySize) {
+ // Put directly in overflow.
+ return getOverflowEntriesMutable().put(key, value);
+ }
+ // Insert new Entry in array.
+ if (entryList.size() == maxArraySize) {
+ // Shift the last array entry into overflow.
+ final Entry lastEntryInArray = entryList.remove(maxArraySize - 1);
+ getOverflowEntriesMutable().put(lastEntryInArray.getKey(),
+ lastEntryInArray.getValue());
+ }
+ entryList.add(insertionPoint, new Entry(key, value));
+ return null;
+ }
+
+ @Override
+ public void clear() {
+ checkMutable();
+ if (!entryList.isEmpty()) {
+ entryList.clear();
+ }
+ if (!overflowEntries.isEmpty()) {
+ overflowEntries.clear();
+ }
+ }
+
+ /**
+ * The implementation throws a {@code ClassCastException} if o is not an
+ * object of type {@code K}.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public V remove(Object o) {
+ checkMutable();
+ @SuppressWarnings("unchecked")
+ final K key = (K) o;
+ final int index = binarySearchInArray(key);
+ if (index >= 0) {
+ return removeArrayEntryAt(index);
+ }
+ // overflowEntries might be Collections.unmodifiableMap(), so only
+ // call remove() if it is non-empty.
+ if (overflowEntries.isEmpty()) {
+ return null;
+ } else {
+ return overflowEntries.remove(key);
+ }
+ }
+
+ private V removeArrayEntryAt(int index) {
+ checkMutable();
+ final V removed = entryList.remove(index).getValue();
+ if (!overflowEntries.isEmpty()) {
+ // Shift the first entry in the overflow to be the last entry in the
+ // array.
+ final Iterator<Map.Entry<K, V>> iterator =
+ getOverflowEntriesMutable().entrySet().iterator();
+ entryList.add(new Entry(iterator.next()));
+ iterator.remove();
+ }
+ return removed;
+ }
+
+ /**
+ * @param key The key to find in the entry array.
+ * @return The returned integer position follows the same semantics as the
+ * value returned by {@link java.util.Arrays#binarySearch()}.
+ */
+ private int binarySearchInArray(K key) {
+ int left = 0;
+ int right = entryList.size() - 1;
+
+ // Optimization: For the common case in which entries are added in
+ // ascending tag order, check the largest element in the array before
+ // doing a full binary search.
+ if (right >= 0) {
+ int cmp = key.compareTo(entryList.get(right).getKey());
+ if (cmp > 0) {
+ return -(right + 2); // Insert point is after "right".
+ } else if (cmp == 0) {
+ return right;
+ }
+ }
+
+ while (left <= right) {
+ int mid = (left + right) / 2;
+ int cmp = key.compareTo(entryList.get(mid).getKey());
+ if (cmp < 0) {
+ right = mid - 1;
+ } else if (cmp > 0) {
+ left = mid + 1;
+ } else {
+ return mid;
+ }
+ }
+ return -(left + 1);
+ }
+
+ /**
+ * Similar to the AbstractMap implementation of {@code keySet()} and
+ * {@code values()}, the entry set is created the first time this method is
+ * called, and returned in response to all subsequent calls.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ if (lazyEntrySet == null) {
+ lazyEntrySet = new EntrySet();
+ }
+ return lazyEntrySet;
+ }
+
+
+ /**
+ * @throws UnsupportedOperationException if {@link #makeImmutable()} has
+ * has been called.
+ */
+ private void checkMutable() {
+ if (isImmutable) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * @return a {@link SortedMap} to which overflow entries mappings can be
+ * added or removed.
+ * @throws UnsupportedOperationException if {@link #makeImmutable()} has been
+ * called.
+ */
+ @SuppressWarnings("unchecked")
+ private SortedMap<K, V> getOverflowEntriesMutable() {
+ checkMutable();
+ if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) {
+ overflowEntries = new TreeMap<K, V>();
+ }
+ return (SortedMap<K, V>) overflowEntries;
+ }
+
+ /**
+ * Lazily creates the entry list. Any code that adds to the list must first
+ * call this method.
+ */
+ private void ensureEntryArrayMutable() {
+ checkMutable();
+ if (entryList.isEmpty() && !(entryList instanceof ArrayList)) {
+ entryList = new ArrayList<Entry>(maxArraySize);
+ }
+ }
+
+ /**
+ * Entry implementation that implements Comparable in order to support
+ * binary search within the entry array. Also checks mutability in
+ * {@link #setValue()}.
+ */
+ private class Entry implements Map.Entry<K, V>, Comparable<Entry> {
+
+ private final K key;
+ private V value;
+
+ Entry(Map.Entry<K, V> copy) {
+ this(copy.getKey(), copy.getValue());
+ }
+
+ Entry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public int compareTo(Entry other) {
+ return getKey().compareTo(other.getKey());
+ }
+
+ @Override
+ public V setValue(V newValue) {
+ checkMutable();
+ final V oldValue = this.value;
+ this.value = newValue;
+ return oldValue;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Map.Entry)) {
+ return false;
+ }
+ @SuppressWarnings("unchecked")
+ Map.Entry<?, ?> other = (Map.Entry<?, ?>) o;
+ return equals(key, other.getKey()) && equals(value, other.getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return (key == null ? 0 : key.hashCode()) ^
+ (value == null ? 0 : value.hashCode());
+ }
+
+ @Override
+ public String toString() {
+ return key + "=" + value;
+ }
+
+ /** equals() that handles null values. */
+ private boolean equals(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+ }
+
+ /**
+ * Stateless view of the entries in the field map.
+ */
+ private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
+
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator() {
+ return new EntryIterator();
+ }
+
+ @Override
+ public int size() {
+ return SmallSortedMap.this.size();
+ }
+
+ /**
+ * Throws a {@link ClassCastException} if o is not of the expected type.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean contains(Object o) {
+ @SuppressWarnings("unchecked")
+ final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+ final V existing = get(entry.getKey());
+ final V value = entry.getValue();
+ return existing == value ||
+ (existing != null && existing.equals(value));
+ }
+
+ @Override
+ public boolean add(Map.Entry<K, V> entry) {
+ if (!contains(entry)) {
+ put(entry.getKey(), entry.getValue());
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Throws a {@link ClassCastException} if o is not of the expected type.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean remove(Object o) {
+ @SuppressWarnings("unchecked")
+ final Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+ if (contains(entry)) {
+ SmallSortedMap.this.remove(entry.getKey());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void clear() {
+ SmallSortedMap.this.clear();
+ }
+ }
+
+
+ /**
+ * Iterator implementation that switches from the entry array to the overflow
+ * entries appropriately.
+ */
+ private class EntryIterator implements Iterator<Map.Entry<K, V>> {
+
+ private int pos = -1;
+ private boolean nextCalledBeforeRemove;
+ private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
+
+ @Override
+ public boolean hasNext() {
+ return (pos + 1) < entryList.size() ||
+ getOverflowIterator().hasNext();
+ }
+
+ @Override
+ public Map.Entry<K, V> next() {
+ nextCalledBeforeRemove = true;
+ // Always increment pos so that we know whether the last returned value
+ // was from the array or from overflow.
+ if (++pos < entryList.size()) {
+ return entryList.get(pos);
+ }
+ return getOverflowIterator().next();
+ }
+
+ @Override
+ public void remove() {
+ if (!nextCalledBeforeRemove) {
+ throw new IllegalStateException("remove() was called before next()");
+ }
+ nextCalledBeforeRemove = false;
+ checkMutable();
+
+ if (pos < entryList.size()) {
+ removeArrayEntryAt(pos--);
+ } else {
+ getOverflowIterator().remove();
+ }
+ }
+
+ /**
+ * It is important to create the overflow iterator only after the array
+ * entries have been iterated over because the overflow entry set changes
+ * when the client calls remove() on the array entries, which invalidates
+ * any existing iterators.
+ */
+ private Iterator<Map.Entry<K, V>> getOverflowIterator() {
+ if (lazyOverflowIterator == null) {
+ lazyOverflowIterator = overflowEntries.entrySet().iterator();
+ }
+ return lazyOverflowIterator;
+ }
+ }
+
+ /**
+ * Helper class that holds immutable instances of an Iterable/Iterator that
+ * we return when the overflow entries is empty. This eliminates the creation
+ * of an Iterator object when there is nothing to iterate over.
+ */
+ private static class EmptySet {
+
+ private static final Iterator<Object> ITERATOR =
+ new Iterator<Object>() {
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+ @Override
+ public Object next() {
+ throw new NoSuchElementException();
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ private static final Iterable<Object> ITERABLE =
+ new Iterable<Object>() {
+ @Override
+ public Iterator<Object> iterator() {
+ return ITERATOR;
+ }
+ };
+
+ @SuppressWarnings("unchecked")
+ static <T> Iterable<T> iterable() {
+ return (Iterable<T>) ITERABLE;
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof SmallSortedMap)) {
+ return super.equals(o);
+ }
+
+ SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o;
+ final int size = size();
+ if (size != other.size()) {
+ return false;
+ }
+
+ // Best effort try to avoid allocating an entry set.
+ final int numArrayEntries = getNumArrayEntries();
+ if (numArrayEntries != other.getNumArrayEntries()) {
+ return entrySet().equals(other.entrySet());
+ }
+
+ for (int i = 0; i < numArrayEntries; i++) {
+ if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) {
+ return false;
+ }
+ }
+
+ if (numArrayEntries != size) {
+ return overflowEntries.equals(other.overflowEntries);
+ }
+
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = 0;
+ final int listSize = getNumArrayEntries();
+ for (int i = 0; i < listSize; i++) {
+ h += entryList.get(i).hashCode();
+ }
+ // Avoid the iterator allocation if possible.
+ if (getNumOverflowEntries() > 0) {
+ h += overflowEntries.hashCode();
+ }
+ return h;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormat.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormat.java
new file mode 100644
index 0000000000..4970824215
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -0,0 +1,2108 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Provide text parsing and formatting support for proto2 instances.
+ * The implementation largely follows google/protobuf/text_format.cc.
+ *
+ * @author wenboz@google.com Wenbo Zhu
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TextFormat {
+ private TextFormat() {}
+
+ private static final Logger logger =
+ Logger.getLogger(TextFormat.class.getName());
+
+ private static final Printer DEFAULT_PRINTER = new Printer();
+ private static final Printer SINGLE_LINE_PRINTER =
+ (new Printer()).setSingleLineMode(true);
+ private static final Printer UNICODE_PRINTER =
+ (new Printer()).setEscapeNonAscii(false);
+
+ /**
+ * Outputs a textual representation of the Protocol Message supplied into
+ * the parameter output. (This representation is the new version of the
+ * classic "ProtocolPrinter" output from the original Protocol Buffer system)
+ */
+ public static void print(
+ final MessageOrBuilder message, final Appendable output)
+ throws IOException {
+ DEFAULT_PRINTER.print(message, new TextGenerator(output));
+ }
+
+ /** Outputs a textual representation of {@code fields} to {@code output}. */
+ public static void print(final UnknownFieldSet fields,
+ final Appendable output)
+ throws IOException {
+ DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+ }
+
+ /**
+ * Same as {@code print()}, except that non-ASCII characters are not
+ * escaped.
+ */
+ public static void printUnicode(
+ final MessageOrBuilder message, final Appendable output)
+ throws IOException {
+ UNICODE_PRINTER.print(message, new TextGenerator(output));
+ }
+
+ /**
+ * Same as {@code print()}, except that non-ASCII characters are not
+ * escaped.
+ */
+ public static void printUnicode(final UnknownFieldSet fields,
+ final Appendable output)
+ throws IOException {
+ UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+ }
+
+ /**
+ * Generates a human readable form of this message, useful for debugging and
+ * other purposes, with no newline characters.
+ */
+ public static String shortDebugString(final MessageOrBuilder message) {
+ try {
+ final StringBuilder sb = new StringBuilder();
+ SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
+ // Single line mode currently might have an extra space at the end.
+ return sb.toString().trim();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Generates a human readable form of the field, useful for debugging
+ * and other purposes, with no newline characters.
+ */
+ public static String shortDebugString(final FieldDescriptor field,
+ final Object value) {
+ try {
+ final StringBuilder sb = new StringBuilder();
+ SINGLE_LINE_PRINTER.printField(field, value, new TextGenerator(sb));
+ return sb.toString().trim();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Generates a human readable form of the unknown fields, useful for debugging
+ * and other purposes, with no newline characters.
+ */
+ public static String shortDebugString(final UnknownFieldSet fields) {
+ try {
+ final StringBuilder sb = new StringBuilder();
+ SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb));
+ // Single line mode currently might have an extra space at the end.
+ return sb.toString().trim();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Like {@code print()}, but writes directly to a {@code String} and
+ * returns it.
+ */
+ public static String printToString(final MessageOrBuilder message) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ print(message, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Like {@code print()}, but writes directly to a {@code String} and
+ * returns it.
+ */
+ public static String printToString(final UnknownFieldSet fields) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ print(fields, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Same as {@code printToString()}, except that non-ASCII characters
+ * in string type fields are not escaped in backslash+octals.
+ */
+ public static String printToUnicodeString(final MessageOrBuilder message) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ UNICODE_PRINTER.print(message, new TextGenerator(text));
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Same as {@code printToString()}, except that non-ASCII characters
+ * in string type fields are not escaped in backslash+octals.
+ */
+ public static String printToUnicodeString(final UnknownFieldSet fields) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public static void printField(final FieldDescriptor field,
+ final Object value,
+ final Appendable output)
+ throws IOException {
+ DEFAULT_PRINTER.printField(field, value, new TextGenerator(output));
+ }
+
+ public static String printFieldToString(final FieldDescriptor field,
+ final Object value) {
+ try {
+ final StringBuilder text = new StringBuilder();
+ printField(field, value, text);
+ return text.toString();
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Outputs a textual representation of the value of given field value.
+ *
+ * @param field the descriptor of the field
+ * @param value the value of the field
+ * @param output the output to which to append the formatted value
+ * @throws ClassCastException if the value is not appropriate for the
+ * given field descriptor
+ * @throws IOException if there is an exception writing to the output
+ */
+ public static void printFieldValue(final FieldDescriptor field,
+ final Object value,
+ final Appendable output)
+ throws IOException {
+ DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output));
+ }
+
+ /**
+ * Outputs a textual representation of the value of an unknown field.
+ *
+ * @param tag the field's tag number
+ * @param value the value of the field
+ * @param output the output to which to append the formatted value
+ * @throws ClassCastException if the value is not appropriate for the
+ * given field descriptor
+ * @throws IOException if there is an exception writing to the output
+ */
+ public static void printUnknownFieldValue(final int tag,
+ final Object value,
+ final Appendable output)
+ throws IOException {
+ printUnknownFieldValue(tag, value, new TextGenerator(output));
+ }
+
+ private static void printUnknownFieldValue(final int tag,
+ final Object value,
+ final TextGenerator generator)
+ throws IOException {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ generator.print(unsignedToString((Long) value));
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ generator.print(
+ String.format((Locale) null, "0x%08x", (Integer) value));
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ generator.print(String.format((Locale) null, "0x%016x", (Long) value));
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ generator.print("\"");
+ generator.print(escapeBytes((ByteString) value));
+ generator.print("\"");
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator);
+ break;
+ default:
+ throw new IllegalArgumentException("Bad tag: " + tag);
+ }
+ }
+
+ /** Helper class for converting protobufs to text. */
+ private static final class Printer {
+ /** Whether to omit newlines from the output. */
+ boolean singleLineMode = false;
+
+ /** Whether to escape non ASCII characters with backslash and octal. */
+ boolean escapeNonAscii = true;
+
+ private Printer() {}
+
+ /** Setter of singleLineMode */
+ private Printer setSingleLineMode(boolean singleLineMode) {
+ this.singleLineMode = singleLineMode;
+ return this;
+ }
+
+ /** Setter of escapeNonAscii */
+ private Printer setEscapeNonAscii(boolean escapeNonAscii) {
+ this.escapeNonAscii = escapeNonAscii;
+ return this;
+ }
+
+ private void print(
+ final MessageOrBuilder message, final TextGenerator generator)
+ throws IOException {
+ for (Map.Entry<FieldDescriptor, Object> field
+ : message.getAllFields().entrySet()) {
+ printField(field.getKey(), field.getValue(), generator);
+ }
+ printUnknownFields(message.getUnknownFields(), generator);
+ }
+
+ private void printField(final FieldDescriptor field, final Object value,
+ final TextGenerator generator) throws IOException {
+ if (field.isRepeated()) {
+ // Repeated field. Print each element.
+ for (Object element : (List<?>) value) {
+ printSingleField(field, element, generator);
+ }
+ } else {
+ printSingleField(field, value, generator);
+ }
+ }
+
+ private void printSingleField(final FieldDescriptor field,
+ final Object value,
+ final TextGenerator generator)
+ throws IOException {
+ if (field.isExtension()) {
+ generator.print("[");
+ // We special-case MessageSet elements for compatibility with proto1.
+ if (field.getContainingType().getOptions().getMessageSetWireFormat()
+ && (field.getType() == FieldDescriptor.Type.MESSAGE)
+ && (field.isOptional())
+ // object equality
+ && (field.getExtensionScope() == field.getMessageType())) {
+ generator.print(field.getMessageType().getFullName());
+ } else {
+ generator.print(field.getFullName());
+ }
+ generator.print("]");
+ } else {
+ if (field.getType() == FieldDescriptor.Type.GROUP) {
+ // Groups must be serialized with their original capitalization.
+ generator.print(field.getMessageType().getName());
+ } else {
+ generator.print(field.getName());
+ }
+ }
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (singleLineMode) {
+ generator.print(" { ");
+ } else {
+ generator.print(" {\n");
+ generator.indent();
+ }
+ } else {
+ generator.print(": ");
+ }
+
+ printFieldValue(field, value, generator);
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (singleLineMode) {
+ generator.print("} ");
+ } else {
+ generator.outdent();
+ generator.print("}\n");
+ }
+ } else {
+ if (singleLineMode) {
+ generator.print(" ");
+ } else {
+ generator.print("\n");
+ }
+ }
+ }
+
+ private void printFieldValue(final FieldDescriptor field,
+ final Object value,
+ final TextGenerator generator)
+ throws IOException {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ generator.print(((Integer) value).toString());
+ break;
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ generator.print(((Long) value).toString());
+ break;
+
+ case BOOL:
+ generator.print(((Boolean) value).toString());
+ break;
+
+ case FLOAT:
+ generator.print(((Float) value).toString());
+ break;
+
+ case DOUBLE:
+ generator.print(((Double) value).toString());
+ break;
+
+ case UINT32:
+ case FIXED32:
+ generator.print(unsignedToString((Integer) value));
+ break;
+
+ case UINT64:
+ case FIXED64:
+ generator.print(unsignedToString((Long) value));
+ break;
+
+ case STRING:
+ generator.print("\"");
+ generator.print(escapeNonAscii
+ ? TextFormatEscaper.escapeText((String) value)
+ : escapeDoubleQuotesAndBackslashes((String) value)
+ .replace("\n", "\\n"));
+ generator.print("\"");
+ break;
+
+ case BYTES:
+ generator.print("\"");
+ if (value instanceof ByteString) {
+ generator.print(escapeBytes((ByteString) value));
+ } else {
+ generator.print(escapeBytes((byte[]) value));
+ }
+ generator.print("\"");
+ break;
+
+ case ENUM:
+ generator.print(((EnumValueDescriptor) value).getName());
+ break;
+
+ case MESSAGE:
+ case GROUP:
+ print((Message) value, generator);
+ break;
+ }
+ }
+
+ private void printUnknownFields(final UnknownFieldSet unknownFields,
+ final TextGenerator generator)
+ throws IOException {
+ for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+ unknownFields.asMap().entrySet()) {
+ final int number = entry.getKey();
+ final UnknownFieldSet.Field field = entry.getValue();
+ printUnknownField(number, WireFormat.WIRETYPE_VARINT,
+ field.getVarintList(), generator);
+ printUnknownField(number, WireFormat.WIRETYPE_FIXED32,
+ field.getFixed32List(), generator);
+ printUnknownField(number, WireFormat.WIRETYPE_FIXED64,
+ field.getFixed64List(), generator);
+ printUnknownField(number, WireFormat.WIRETYPE_LENGTH_DELIMITED,
+ field.getLengthDelimitedList(), generator);
+ for (final UnknownFieldSet value : field.getGroupList()) {
+ generator.print(entry.getKey().toString());
+ if (singleLineMode) {
+ generator.print(" { ");
+ } else {
+ generator.print(" {\n");
+ generator.indent();
+ }
+ printUnknownFields(value, generator);
+ if (singleLineMode) {
+ generator.print("} ");
+ } else {
+ generator.outdent();
+ generator.print("}\n");
+ }
+ }
+ }
+ }
+
+ private void printUnknownField(final int number,
+ final int wireType,
+ final List<?> values,
+ final TextGenerator generator)
+ throws IOException {
+ for (final Object value : values) {
+ generator.print(String.valueOf(number));
+ generator.print(": ");
+ printUnknownFieldValue(wireType, value, generator);
+ generator.print(singleLineMode ? " " : "\n");
+ }
+ }
+ }
+
+ /** Convert an unsigned 32-bit integer to a string. */
+ public static String unsignedToString(final int value) {
+ if (value >= 0) {
+ return Integer.toString(value);
+ } else {
+ return Long.toString(value & 0x00000000FFFFFFFFL);
+ }
+ }
+
+ /** Convert an unsigned 64-bit integer to a string. */
+ public static String unsignedToString(final long value) {
+ if (value >= 0) {
+ return Long.toString(value);
+ } else {
+ // Pull off the most-significant bit so that BigInteger doesn't think
+ // the number is negative, then set it again using setBit().
+ return BigInteger.valueOf(value & 0x7FFFFFFFFFFFFFFFL)
+ .setBit(63).toString();
+ }
+ }
+
+ /**
+ * An inner class for writing text to the output stream.
+ */
+ private static final class TextGenerator {
+ private final Appendable output;
+ private final StringBuilder indent = new StringBuilder();
+ private boolean atStartOfLine = true;
+
+ private TextGenerator(final Appendable output) {
+ this.output = output;
+ }
+
+ /**
+ * Indent text by two spaces. After calling Indent(), two spaces will be
+ * inserted at the beginning of each line of text. Indent() may be called
+ * multiple times to produce deeper indents.
+ */
+ public void indent() {
+ indent.append(" ");
+ }
+
+ /**
+ * Reduces the current indent level by two spaces, or crashes if the indent
+ * level is zero.
+ */
+ public void outdent() {
+ final int length = indent.length();
+ if (length == 0) {
+ throw new IllegalArgumentException(
+ " Outdent() without matching Indent().");
+ }
+ indent.delete(length - 2, length);
+ }
+
+ /**
+ * Print text to the output stream.
+ */
+ public void print(final CharSequence text) throws IOException {
+ final int size = text.length();
+ int pos = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (text.charAt(i) == '\n') {
+ write(text.subSequence(pos, i + 1));
+ pos = i + 1;
+ atStartOfLine = true;
+ }
+ }
+ write(text.subSequence(pos, size));
+ }
+
+ private void write(final CharSequence data) throws IOException {
+ if (data.length() == 0) {
+ return;
+ }
+ if (atStartOfLine) {
+ atStartOfLine = false;
+ output.append(indent);
+ }
+ output.append(data);
+ }
+ }
+
+ // =================================================================
+ // Parsing
+
+ /**
+ * Represents a stream of tokens parsed from a {@code String}.
+ *
+ * <p>The Java standard library provides many classes that you might think
+ * would be useful for implementing this, but aren't. For example:
+ *
+ * <ul>
+ * <li>{@code java.io.StreamTokenizer}: This almost does what we want -- or,
+ * at least, something that would get us close to what we want -- except
+ * for one fatal flaw: It automatically un-escapes strings using Java
+ * escape sequences, which do not include all the escape sequences we
+ * need to support (e.g. '\x').
+ * <li>{@code java.util.Scanner}: This seems like a great way at least to
+ * parse regular expressions out of a stream (so we wouldn't have to load
+ * the entire input into a single string before parsing). Sadly,
+ * {@code Scanner} requires that tokens be delimited with some delimiter.
+ * Thus, although the text "foo:" should parse to two tokens ("foo" and
+ * ":"), {@code Scanner} would recognize it only as a single token.
+ * Furthermore, {@code Scanner} provides no way to inspect the contents
+ * of delimiters, making it impossible to keep track of line and column
+ * numbers.
+ * </ul>
+ *
+ * <p>Luckily, Java's regular expression support does manage to be useful to
+ * us. (Barely: We need {@code Matcher.usePattern()}, which is new in
+ * Java 1.5.) So, we can use that, at least. Unfortunately, this implies
+ * that we need to have the entire input in one contiguous string.
+ */
+ private static final class Tokenizer {
+ private final CharSequence text;
+ private final Matcher matcher;
+ private String currentToken;
+
+ // The character index within this.text at which the current token begins.
+ private int pos = 0;
+
+ // The line and column numbers of the current token.
+ private int line = 0;
+ private int column = 0;
+
+ // The line and column numbers of the previous token (allows throwing
+ // errors *after* consuming).
+ private int previousLine = 0;
+ private int previousColumn = 0;
+
+ // We use possessive quantifiers (*+ and ++) because otherwise the Java
+ // regex matcher has stack overflows on large inputs.
+ private static final Pattern WHITESPACE =
+ Pattern.compile("(\\s|(#.*$))++", Pattern.MULTILINE);
+ private static final Pattern TOKEN = Pattern.compile(
+ "[a-zA-Z_][0-9a-zA-Z_+-]*+|" + // an identifier
+ "[.]?[0-9+-][0-9a-zA-Z_.+-]*+|" + // a number
+ "\"([^\"\n\\\\]|\\\\.)*+(\"|\\\\?$)|" + // a double-quoted string
+ "\'([^\'\n\\\\]|\\\\.)*+(\'|\\\\?$)", // a single-quoted string
+ Pattern.MULTILINE);
+
+ private static final Pattern DOUBLE_INFINITY = Pattern.compile(
+ "-?inf(inity)?",
+ Pattern.CASE_INSENSITIVE);
+ private static final Pattern FLOAT_INFINITY = Pattern.compile(
+ "-?inf(inity)?f?",
+ Pattern.CASE_INSENSITIVE);
+ private static final Pattern FLOAT_NAN = Pattern.compile(
+ "nanf?",
+ Pattern.CASE_INSENSITIVE);
+
+ /** Construct a tokenizer that parses tokens from the given text. */
+ private Tokenizer(final CharSequence text) {
+ this.text = text;
+ this.matcher = WHITESPACE.matcher(text);
+ skipWhitespace();
+ nextToken();
+ }
+
+ int getPreviousLine() {
+ return previousLine;
+ }
+
+ int getPreviousColumn() {
+ return previousColumn;
+ }
+
+ int getLine() {
+ return line;
+ }
+
+ int getColumn() {
+ return column;
+ }
+
+ /** Are we at the end of the input? */
+ public boolean atEnd() {
+ return currentToken.length() == 0;
+ }
+
+ /** Advance to the next token. */
+ public void nextToken() {
+ previousLine = line;
+ previousColumn = column;
+
+ // Advance the line counter to the current position.
+ while (pos < matcher.regionStart()) {
+ if (text.charAt(pos) == '\n') {
+ ++line;
+ column = 0;
+ } else {
+ ++column;
+ }
+ ++pos;
+ }
+
+ // Match the next token.
+ if (matcher.regionStart() == matcher.regionEnd()) {
+ // EOF
+ currentToken = "";
+ } else {
+ matcher.usePattern(TOKEN);
+ if (matcher.lookingAt()) {
+ currentToken = matcher.group();
+ matcher.region(matcher.end(), matcher.regionEnd());
+ } else {
+ // Take one character.
+ currentToken = String.valueOf(text.charAt(pos));
+ matcher.region(pos + 1, matcher.regionEnd());
+ }
+
+ skipWhitespace();
+ }
+ }
+
+ /**
+ * Skip over any whitespace so that the matcher region starts at the next
+ * token.
+ */
+ private void skipWhitespace() {
+ matcher.usePattern(WHITESPACE);
+ if (matcher.lookingAt()) {
+ matcher.region(matcher.end(), matcher.regionEnd());
+ }
+ }
+
+ /**
+ * If the next token exactly matches {@code token}, consume it and return
+ * {@code true}. Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsume(final String token) {
+ if (currentToken.equals(token)) {
+ nextToken();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token exactly matches {@code token}, consume it. Otherwise,
+ * throw a {@link ParseException}.
+ */
+ public void consume(final String token) throws ParseException {
+ if (!tryConsume(token)) {
+ throw parseException("Expected \"" + token + "\".");
+ }
+ }
+
+ /**
+ * Returns {@code true} if the next token is an integer, but does
+ * not consume it.
+ */
+ public boolean lookingAtInteger() {
+ if (currentToken.length() == 0) {
+ return false;
+ }
+
+ final char c = currentToken.charAt(0);
+ return ('0' <= c && c <= '9')
+ || c == '-' || c == '+';
+ }
+
+ /**
+ * Returns {@code true} if the current token's text is equal to that
+ * specified.
+ */
+ public boolean lookingAt(String text) {
+ return currentToken.equals(text);
+ }
+
+ /**
+ * If the next token is an identifier, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public String consumeIdentifier() throws ParseException {
+ for (int i = 0; i < currentToken.length(); i++) {
+ final char c = currentToken.charAt(i);
+ if (('a' <= c && c <= 'z')
+ || ('A' <= c && c <= 'Z')
+ || ('0' <= c && c <= '9')
+ || (c == '_') || (c == '.')) {
+ // OK
+ } else {
+ throw parseException(
+ "Expected identifier. Found '" + currentToken + "'");
+ }
+ }
+
+ final String result = currentToken;
+ nextToken();
+ return result;
+ }
+
+ /**
+ * If the next token is an identifier, consume it and return {@code true}.
+ * Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsumeIdentifier() {
+ try {
+ consumeIdentifier();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a 32-bit signed integer, consume it and return its
+ * value. Otherwise, throw a {@link ParseException}.
+ */
+ public int consumeInt32() throws ParseException {
+ try {
+ final int result = parseInt32(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 32-bit unsigned integer, consume it and return its
+ * value. Otherwise, throw a {@link ParseException}.
+ */
+ public int consumeUInt32() throws ParseException {
+ try {
+ final int result = parseUInt32(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit signed integer, consume it and return its
+ * value. Otherwise, throw a {@link ParseException}.
+ */
+ public long consumeInt64() throws ParseException {
+ try {
+ final long result = parseInt64(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit signed integer, consume it and return
+ * {@code true}. Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsumeInt64() {
+ try {
+ consumeInt64();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit unsigned integer, consume it and return its
+ * value. Otherwise, throw a {@link ParseException}.
+ */
+ public long consumeUInt64() throws ParseException {
+ try {
+ final long result = parseUInt64(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw integerParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a 64-bit unsigned integer, consume it and return
+ * {@code true}. Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsumeUInt64() {
+ try {
+ consumeUInt64();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a double, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public double consumeDouble() throws ParseException {
+ // We need to parse infinity and nan separately because
+ // Double.parseDouble() does not accept "inf", "infinity", or "nan".
+ if (DOUBLE_INFINITY.matcher(currentToken).matches()) {
+ final boolean negative = currentToken.startsWith("-");
+ nextToken();
+ return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if (currentToken.equalsIgnoreCase("nan")) {
+ nextToken();
+ return Double.NaN;
+ }
+ try {
+ final double result = Double.parseDouble(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw floatParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a double, consume it and return {@code true}.
+ * Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsumeDouble() {
+ try {
+ consumeDouble();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a float, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public float consumeFloat() throws ParseException {
+ // We need to parse infinity and nan separately because
+ // Float.parseFloat() does not accept "inf", "infinity", or "nan".
+ if (FLOAT_INFINITY.matcher(currentToken).matches()) {
+ final boolean negative = currentToken.startsWith("-");
+ nextToken();
+ return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
+ if (FLOAT_NAN.matcher(currentToken).matches()) {
+ nextToken();
+ return Float.NaN;
+ }
+ try {
+ final float result = Float.parseFloat(currentToken);
+ nextToken();
+ return result;
+ } catch (NumberFormatException e) {
+ throw floatParseException(e);
+ }
+ }
+
+ /**
+ * If the next token is a float, consume it and return {@code true}.
+ * Otherwise, return {@code false} without doing anything.
+ */
+ public boolean tryConsumeFloat() {
+ try {
+ consumeFloat();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a boolean, consume it and return its value.
+ * Otherwise, throw a {@link ParseException}.
+ */
+ public boolean consumeBoolean() throws ParseException {
+ if (currentToken.equals("true")
+ || currentToken.equals("True")
+ || currentToken.equals("t")
+ || currentToken.equals("1")) {
+ nextToken();
+ return true;
+ } else if (currentToken.equals("false")
+ || currentToken.equals("False")
+ || currentToken.equals("f")
+ || currentToken.equals("0")) {
+ nextToken();
+ return false;
+ } else {
+ throw parseException("Expected \"true\" or \"false\".");
+ }
+ }
+
+ /**
+ * If the next token is a string, consume it and return its (unescaped)
+ * value. Otherwise, throw a {@link ParseException}.
+ */
+ public String consumeString() throws ParseException {
+ return consumeByteString().toStringUtf8();
+ }
+
+ /**
+ * If the next token is a string, consume it and return true. Otherwise,
+ * return false.
+ */
+ public boolean tryConsumeString() {
+ try {
+ consumeString();
+ return true;
+ } catch (ParseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * If the next token is a string, consume it, unescape it as a
+ * {@link ByteString}, and return it. Otherwise, throw a
+ * {@link ParseException}.
+ */
+ public ByteString consumeByteString() throws ParseException {
+ List<ByteString> list = new ArrayList<ByteString>();
+ consumeByteString(list);
+ while (currentToken.startsWith("'") || currentToken.startsWith("\"")) {
+ consumeByteString(list);
+ }
+ return ByteString.copyFrom(list);
+ }
+
+ /**
+ * Like {@link #consumeByteString()} but adds each token of the string to
+ * the given list. String literals (whether bytes or text) may come in
+ * multiple adjacent tokens which are automatically concatenated, like in
+ * C or Python.
+ */
+ private void consumeByteString(List<ByteString> list)
+ throws ParseException {
+ final char quote = currentToken.length() > 0
+ ? currentToken.charAt(0)
+ : '\0';
+ if (quote != '\"' && quote != '\'') {
+ throw parseException("Expected string.");
+ }
+
+ if (currentToken.length() < 2
+ || currentToken.charAt(currentToken.length() - 1) != quote) {
+ throw parseException("String missing ending quote.");
+ }
+
+ try {
+ final String escaped =
+ currentToken.substring(1, currentToken.length() - 1);
+ final ByteString result = unescapeBytes(escaped);
+ nextToken();
+ list.add(result);
+ } catch (InvalidEscapeSequenceException e) {
+ throw parseException(e.getMessage());
+ }
+ }
+
+ /**
+ * Returns a {@link ParseException} with the current line and column
+ * numbers in the description, suitable for throwing.
+ */
+ public ParseException parseException(final String description) {
+ // Note: People generally prefer one-based line and column numbers.
+ return new ParseException(
+ line + 1, column + 1, description);
+ }
+
+ /**
+ * Returns a {@link ParseException} with the line and column numbers of
+ * the previous token in the description, suitable for throwing.
+ */
+ public ParseException parseExceptionPreviousToken(
+ final String description) {
+ // Note: People generally prefer one-based line and column numbers.
+ return new ParseException(
+ previousLine + 1, previousColumn + 1, description);
+ }
+
+ /**
+ * Constructs an appropriate {@link ParseException} for the given
+ * {@code NumberFormatException} when trying to parse an integer.
+ */
+ private ParseException integerParseException(
+ final NumberFormatException e) {
+ return parseException("Couldn't parse integer: " + e.getMessage());
+ }
+
+ /**
+ * Constructs an appropriate {@link ParseException} for the given
+ * {@code NumberFormatException} when trying to parse a float or double.
+ */
+ private ParseException floatParseException(final NumberFormatException e) {
+ return parseException("Couldn't parse number: " + e.getMessage());
+ }
+
+ /**
+ * Returns a {@link UnknownFieldParseException} with the line and column
+ * numbers of the previous token in the description, and the unknown field
+ * name, suitable for throwing.
+ */
+ public UnknownFieldParseException unknownFieldParseExceptionPreviousToken(
+ final String unknownField, final String description) {
+ // Note: People generally prefer one-based line and column numbers.
+ return new UnknownFieldParseException(
+ previousLine + 1, previousColumn + 1, unknownField, description);
+ }
+ }
+
+ /** Thrown when parsing an invalid text format message. */
+ public static class ParseException extends IOException {
+ private static final long serialVersionUID = 3196188060225107702L;
+
+ private final int line;
+ private final int column;
+
+ /** Create a new instance, with -1 as the line and column numbers. */
+ public ParseException(final String message) {
+ this(-1, -1, message);
+ }
+
+ /**
+ * Create a new instance
+ *
+ * @param line the line number where the parse error occurred,
+ * using 1-offset.
+ * @param column the column number where the parser error occurred,
+ * using 1-offset.
+ */
+ public ParseException(final int line, final int column,
+ final String message) {
+ super(Integer.toString(line) + ":" + column + ": " + message);
+ this.line = line;
+ this.column = column;
+ }
+
+ /**
+ * Return the line where the parse exception occurred, or -1 when
+ * none is provided. The value is specified as 1-offset, so the first
+ * line is line 1.
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Return the column where the parse exception occurred, or -1 when
+ * none is provided. The value is specified as 1-offset, so the first
+ * line is line 1.
+ */
+ public int getColumn() {
+ return column;
+ }
+ }
+
+ /**
+ * Thrown when encountering an unknown field while parsing
+ * a text format message.
+ */
+ public static class UnknownFieldParseException extends ParseException {
+ private final String unknownField;
+
+ /**
+ * Create a new instance, with -1 as the line and column numbers, and an
+ * empty unknown field name.
+ */
+ public UnknownFieldParseException(final String message) {
+ this(-1, -1, "", message);
+ }
+
+ /**
+ * Create a new instance
+ *
+ * @param line the line number where the parse error occurred,
+ * using 1-offset.
+ * @param column the column number where the parser error occurred,
+ * using 1-offset.
+ * @param unknownField the name of the unknown field found while parsing.
+ */
+ public UnknownFieldParseException(final int line, final int column,
+ final String unknownField, final String message) {
+ super(line, column, message);
+ this.unknownField = unknownField;
+ }
+
+ /**
+ * Return the name of the unknown field encountered while parsing the
+ * protocol buffer string.
+ */
+ public String getUnknownField() {
+ return unknownField;
+ }
+ }
+
+ private static final Parser PARSER = Parser.newBuilder().build();
+
+ /**
+ * Return a {@link Parser} instance which can parse text-format
+ * messages. The returned instance is thread-safe.
+ */
+ public static Parser getParser() {
+ return PARSER;
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}.
+ */
+ public static void merge(final Readable input,
+ final Message.Builder builder)
+ throws IOException {
+ PARSER.merge(input, builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}.
+ */
+ public static void merge(final CharSequence input,
+ final Message.Builder builder)
+ throws ParseException {
+ PARSER.merge(input, builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}. Extensions will be recognized if they are
+ * registered in {@code extensionRegistry}.
+ */
+ public static void merge(final Readable input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
+ throws IOException {
+ PARSER.merge(input, extensionRegistry, builder);
+ }
+
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}. Extensions will be recognized if they are
+ * registered in {@code extensionRegistry}.
+ */
+ public static void merge(final CharSequence input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
+ throws ParseException {
+ PARSER.merge(input, extensionRegistry, builder);
+ }
+
+
+ /**
+ * Parser for text-format proto2 instances. This class is thread-safe.
+ * The implementation largely follows google/protobuf/text_format.cc.
+ *
+ * <p>Use {@link TextFormat#getParser()} to obtain the default parser, or
+ * {@link Builder} to control the parser behavior.
+ */
+ public static class Parser {
+ /**
+ * Determines if repeated values for non-repeated fields and
+ * oneofs are permitted. For example, given required/optional field "foo"
+ * and a oneof containing "baz" and "qux":
+ * <ul>
+ * <li>"foo: 1 foo: 2"
+ * <li>"baz: 1 qux: 2"
+ * <li>merging "foo: 2" into a proto in which foo is already set, or
+ * <li>merging "qux: 2" into a proto in which baz is already set.
+ * </ul>
+ */
+ public enum SingularOverwritePolicy {
+ /** The last value is retained. */
+ ALLOW_SINGULAR_OVERWRITES,
+ /** An error is issued. */
+ FORBID_SINGULAR_OVERWRITES
+ }
+
+ private final boolean allowUnknownFields;
+ private final SingularOverwritePolicy singularOverwritePolicy;
+ private TextFormatParseInfoTree.Builder parseInfoTreeBuilder;
+
+ private Parser(
+ boolean allowUnknownFields, SingularOverwritePolicy singularOverwritePolicy,
+ TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
+ this.allowUnknownFields = allowUnknownFields;
+ this.singularOverwritePolicy = singularOverwritePolicy;
+ this.parseInfoTreeBuilder = parseInfoTreeBuilder;
+ }
+
+ /**
+ * Returns a new instance of {@link Builder}.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder that can be used to obtain new instances of {@link Parser}.
+ */
+ public static class Builder {
+ private boolean allowUnknownFields = false;
+ private SingularOverwritePolicy singularOverwritePolicy =
+ SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
+ private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
+
+
+ /**
+ * Sets parser behavior when a non-repeated field appears more than once.
+ */
+ public Builder setSingularOverwritePolicy(SingularOverwritePolicy p) {
+ this.singularOverwritePolicy = p;
+ return this;
+ }
+
+ public Builder setParseInfoTreeBuilder(
+ TextFormatParseInfoTree.Builder parseInfoTreeBuilder) {
+ this.parseInfoTreeBuilder = parseInfoTreeBuilder;
+ return this;
+ }
+
+ public Parser build() {
+ return new Parser(
+ allowUnknownFields, singularOverwritePolicy, parseInfoTreeBuilder);
+ }
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}.
+ */
+ public void merge(final Readable input,
+ final Message.Builder builder)
+ throws IOException {
+ merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}.
+ */
+ public void merge(final CharSequence input,
+ final Message.Builder builder)
+ throws ParseException {
+ merge(input, ExtensionRegistry.getEmptyRegistry(), builder);
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}. Extensions will be recognized if they are
+ * registered in {@code extensionRegistry}.
+ */
+ public void merge(final Readable input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
+ throws IOException {
+ // Read the entire input to a String then parse that.
+
+ // If StreamTokenizer were not quite so crippled, or if there were a kind
+ // of Reader that could read in chunks that match some particular regex,
+ // or if we wanted to write a custom Reader to tokenize our stream, then
+ // we would not have to read to one big String. Alas, none of these is
+ // the case. Oh well.
+
+ merge(toStringBuilder(input), extensionRegistry, builder);
+ }
+
+
+ private static final int BUFFER_SIZE = 4096;
+
+ // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
+ // overhead is worthwhile
+ private static StringBuilder toStringBuilder(final Readable input)
+ throws IOException {
+ final StringBuilder text = new StringBuilder();
+ final CharBuffer buffer = CharBuffer.allocate(BUFFER_SIZE);
+ while (true) {
+ final int n = input.read(buffer);
+ if (n == -1) {
+ break;
+ }
+ buffer.flip();
+ text.append(buffer, 0, n);
+ }
+ return text;
+ }
+
+ // Check both unknown fields and unknown extensions and log warming messages
+ // or throw exceptions according to the flag.
+ private void checkUnknownFields(final List<String> unknownFields)
+ throws ParseException {
+ if (unknownFields.isEmpty()) {
+ return;
+ }
+
+ StringBuilder msg = new StringBuilder("Input contains unknown fields and/or extensions:");
+ for (String field : unknownFields) {
+ msg.append('\n').append(field);
+ }
+
+ if (allowUnknownFields) {
+ logger.warning(msg.toString());
+ } else {
+ String[] lineColumn = unknownFields.get(0).split(":");
+ throw new ParseException(Integer.valueOf(lineColumn[0]),
+ Integer.valueOf(lineColumn[1]), msg.toString());
+ }
+ }
+
+ /**
+ * Parse a text-format message from {@code input} and merge the contents
+ * into {@code builder}. Extensions will be recognized if they are
+ * registered in {@code extensionRegistry}.
+ */
+ public void merge(final CharSequence input,
+ final ExtensionRegistry extensionRegistry,
+ final Message.Builder builder)
+ throws ParseException {
+ final Tokenizer tokenizer = new Tokenizer(input);
+ MessageReflection.BuilderAdapter target =
+ new MessageReflection.BuilderAdapter(builder);
+
+ List<String> unknownFields = new ArrayList<String>();
+
+ while (!tokenizer.atEnd()) {
+ mergeField(tokenizer, extensionRegistry, target, unknownFields);
+ }
+
+ checkUnknownFields(unknownFields);
+ }
+
+
+ /**
+ * Parse a single field from {@code tokenizer} and merge it into
+ * {@code builder}.
+ */
+ private void mergeField(final Tokenizer tokenizer,
+ final ExtensionRegistry extensionRegistry,
+ final MessageReflection.MergeTarget target,
+ List<String> unknownFields)
+ throws ParseException {
+ mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder,
+ unknownFields);
+ }
+
+ /**
+ * Parse a single field from {@code tokenizer} and merge it into
+ * {@code builder}.
+ */
+ private void mergeField(final Tokenizer tokenizer,
+ final ExtensionRegistry extensionRegistry,
+ final MessageReflection.MergeTarget target,
+ TextFormatParseInfoTree.Builder parseTreeBuilder,
+ List<String> unknownFields)
+ throws ParseException {
+ FieldDescriptor field = null;
+ int startLine = tokenizer.getLine();
+ int startColumn = tokenizer.getColumn();
+ final Descriptor type = target.getDescriptorForType();
+ ExtensionRegistry.ExtensionInfo extension = null;
+
+ if (tokenizer.tryConsume("[")) {
+ // An extension.
+ final StringBuilder name =
+ new StringBuilder(tokenizer.consumeIdentifier());
+ while (tokenizer.tryConsume(".")) {
+ name.append('.');
+ name.append(tokenizer.consumeIdentifier());
+ }
+
+ extension = target.findExtensionByName(
+ extensionRegistry, name.toString());
+
+ if (extension == null) {
+ unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
+ (tokenizer.getPreviousColumn() + 1) + ":\t" +
+ type.getFullName() + ".[" + name + "]");
+ } else {
+ if (extension.descriptor.getContainingType() != type) {
+ throw tokenizer.parseExceptionPreviousToken(
+ "Extension \"" + name + "\" does not extend message type \""
+ + type.getFullName() + "\".");
+ }
+ field = extension.descriptor;
+ }
+
+ tokenizer.consume("]");
+ } else {
+ final String name = tokenizer.consumeIdentifier();
+ field = type.findFieldByName(name);
+
+ // Group names are expected to be capitalized as they appear in the
+ // .proto file, which actually matches their type names, not their field
+ // names.
+ if (field == null) {
+ // Explicitly specify US locale so that this code does not break when
+ // executing in Turkey.
+ final String lowerName = name.toLowerCase(Locale.US);
+ field = type.findFieldByName(lowerName);
+ // If the case-insensitive match worked but the field is NOT a group,
+ if (field != null && field.getType() != FieldDescriptor.Type.GROUP) {
+ field = null;
+ }
+ }
+ // Again, special-case group names as described above.
+ if (field != null && field.getType() == FieldDescriptor.Type.GROUP
+ && !field.getMessageType().getName().equals(name)) {
+ field = null;
+ }
+
+ if (field == null) {
+ unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
+ (tokenizer.getPreviousColumn() + 1) + ":\t" +
+ type.getFullName() + "." + name);
+ }
+ }
+
+ // Skips unknown fields.
+ if (field == null) {
+ // Try to guess the type of this field.
+ // If this field is not a message, there should be a ":" between the
+ // field name and the field value and also the field value should not
+ // start with "{" or "<" which indicates the beginning of a message body.
+ // If there is no ":" or there is a "{" or "<" after ":", this field has
+ // to be a message or the input is ill-formed.
+ if (tokenizer.tryConsume(":")
+ && !tokenizer.lookingAt("{")
+ && !tokenizer.lookingAt("<")) {
+ skipFieldValue(tokenizer);
+ } else {
+ skipFieldMessage(tokenizer);
+ }
+ return;
+ }
+
+ // Handle potential ':'.
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ tokenizer.tryConsume(":"); // optional
+ if (parseTreeBuilder != null) {
+ TextFormatParseInfoTree.Builder childParseTreeBuilder =
+ parseTreeBuilder.getBuilderForSubMessageField(field);
+ consumeFieldValues(tokenizer, extensionRegistry, target, field, extension,
+ childParseTreeBuilder, unknownFields);
+ } else {
+ consumeFieldValues(tokenizer, extensionRegistry, target, field, extension,
+ parseTreeBuilder, unknownFields);
+ }
+ } else {
+ tokenizer.consume(":"); // required
+ consumeFieldValues(tokenizer, extensionRegistry, target, field,
+ extension, parseTreeBuilder, unknownFields);
+ }
+
+ if (parseTreeBuilder != null) {
+ parseTreeBuilder.setLocation(
+ field, TextFormatParseLocation.create(startLine, startColumn));
+ }
+
+ // For historical reasons, fields may optionally be separated by commas or
+ // semicolons.
+ if (!tokenizer.tryConsume(";")) {
+ tokenizer.tryConsume(",");
+ }
+ }
+
+ /**
+ * Parse a one or more field values from {@code tokenizer} and merge it into
+ * {@code builder}.
+ */
+ private void consumeFieldValues(
+ final Tokenizer tokenizer,
+ final ExtensionRegistry extensionRegistry,
+ final MessageReflection.MergeTarget target,
+ final FieldDescriptor field,
+ final ExtensionRegistry.ExtensionInfo extension,
+ final TextFormatParseInfoTree.Builder parseTreeBuilder,
+ List<String> unknownFields)
+ throws ParseException {
+ // Support specifying repeated field values as a comma-separated list.
+ // Ex."foo: [1, 2, 3]"
+ if (field.isRepeated() && tokenizer.tryConsume("[")) {
+ if (!tokenizer.tryConsume("]")) { // Allow "foo: []" to be treated as empty.
+ while (true) {
+ consumeFieldValue(
+ tokenizer,
+ extensionRegistry,
+ target,
+ field,
+ extension,
+ parseTreeBuilder,
+ unknownFields);
+ if (tokenizer.tryConsume("]")) {
+ // End of list.
+ break;
+ }
+ tokenizer.consume(",");
+ }
+ }
+ } else {
+ consumeFieldValue(tokenizer, extensionRegistry, target, field,
+ extension, parseTreeBuilder, unknownFields);
+ }
+ }
+
+ /**
+ * Parse a single field value from {@code tokenizer} and merge it into
+ * {@code builder}.
+ */
+ private void consumeFieldValue(
+ final Tokenizer tokenizer,
+ final ExtensionRegistry extensionRegistry,
+ final MessageReflection.MergeTarget target,
+ final FieldDescriptor field,
+ final ExtensionRegistry.ExtensionInfo extension,
+ final TextFormatParseInfoTree.Builder parseTreeBuilder,
+ List<String> unknownFields)
+ throws ParseException {
+ Object value = null;
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ final String endToken;
+ if (tokenizer.tryConsume("<")) {
+ endToken = ">";
+ } else {
+ tokenizer.consume("{");
+ endToken = "}";
+ }
+
+ final MessageReflection.MergeTarget subField;
+ subField = target.newMergeTargetForField(field,
+ (extension == null) ? null : extension.defaultInstance);
+
+ while (!tokenizer.tryConsume(endToken)) {
+ if (tokenizer.atEnd()) {
+ throw tokenizer.parseException(
+ "Expected \"" + endToken + "\".");
+ }
+ mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder,
+ unknownFields);
+ }
+
+ value = subField.finish();
+
+ } else {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ value = tokenizer.consumeInt32();
+ break;
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ value = tokenizer.consumeInt64();
+ break;
+
+ case UINT32:
+ case FIXED32:
+ value = tokenizer.consumeUInt32();
+ break;
+
+ case UINT64:
+ case FIXED64:
+ value = tokenizer.consumeUInt64();
+ break;
+
+ case FLOAT:
+ value = tokenizer.consumeFloat();
+ break;
+
+ case DOUBLE:
+ value = tokenizer.consumeDouble();
+ break;
+
+ case BOOL:
+ value = tokenizer.consumeBoolean();
+ break;
+
+ case STRING:
+ value = tokenizer.consumeString();
+ break;
+
+ case BYTES:
+ value = tokenizer.consumeByteString();
+ break;
+
+ case ENUM:
+ final EnumDescriptor enumType = field.getEnumType();
+
+ if (tokenizer.lookingAtInteger()) {
+ final int number = tokenizer.consumeInt32();
+ value = enumType.findValueByNumber(number);
+ if (value == null) {
+ throw tokenizer.parseExceptionPreviousToken(
+ "Enum type \"" + enumType.getFullName()
+ + "\" has no value with number " + number + '.');
+ }
+ } else {
+ final String id = tokenizer.consumeIdentifier();
+ value = enumType.findValueByName(id);
+ if (value == null) {
+ throw tokenizer.parseExceptionPreviousToken(
+ "Enum type \"" + enumType.getFullName()
+ + "\" has no value named \"" + id + "\".");
+ }
+ }
+
+ break;
+
+ case MESSAGE:
+ case GROUP:
+ throw new RuntimeException("Can't get here.");
+ }
+ }
+
+ if (field.isRepeated()) {
+ target.addRepeatedField(field, value);
+ } else if ((singularOverwritePolicy
+ == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+ && target.hasField(field)) {
+ throw tokenizer.parseExceptionPreviousToken("Non-repeated field \""
+ + field.getFullName() + "\" cannot be overwritten.");
+ } else if ((singularOverwritePolicy
+ == SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+ && field.getContainingOneof() != null
+ && target.hasOneof(field.getContainingOneof())) {
+ Descriptors.OneofDescriptor oneof = field.getContainingOneof();
+ throw tokenizer.parseExceptionPreviousToken("Field \""
+ + field.getFullName() + "\" is specified along with field \""
+ + target.getOneofFieldDescriptor(oneof).getFullName()
+ + "\", another member of oneof \"" + oneof.getName() + "\".");
+ } else {
+ target.setField(field, value);
+ }
+ }
+
+ /**
+ * Skips the next field including the field's name and value.
+ */
+ private void skipField(Tokenizer tokenizer) throws ParseException {
+ if (tokenizer.tryConsume("[")) {
+ // Extension name.
+ do {
+ tokenizer.consumeIdentifier();
+ } while (tokenizer.tryConsume("."));
+ tokenizer.consume("]");
+ } else {
+ tokenizer.consumeIdentifier();
+ }
+
+ // Try to guess the type of this field.
+ // If this field is not a message, there should be a ":" between the
+ // field name and the field value and also the field value should not
+ // start with "{" or "<" which indicates the beginning of a message body.
+ // If there is no ":" or there is a "{" or "<" after ":", this field has
+ // to be a message or the input is ill-formed.
+ if (tokenizer.tryConsume(":")
+ && !tokenizer.lookingAt("<")
+ && !tokenizer.lookingAt("{")) {
+ skipFieldValue(tokenizer);
+ } else {
+ skipFieldMessage(tokenizer);
+ }
+ // For historical reasons, fields may optionally be separated by commas or
+ // semicolons.
+ if (!tokenizer.tryConsume(";")) {
+ tokenizer.tryConsume(",");
+ }
+ }
+
+ /**
+ * Skips the whole body of a message including the beginning delimiter and
+ * the ending delimiter.
+ */
+ private void skipFieldMessage(Tokenizer tokenizer) throws ParseException {
+ final String delimiter;
+ if (tokenizer.tryConsume("<")) {
+ delimiter = ">";
+ } else {
+ tokenizer.consume("{");
+ delimiter = "}";
+ }
+ while (!tokenizer.lookingAt(">") && !tokenizer.lookingAt("}")) {
+ skipField(tokenizer);
+ }
+ tokenizer.consume(delimiter);
+ }
+
+ /**
+ * Skips a field value.
+ */
+ private void skipFieldValue(Tokenizer tokenizer) throws ParseException {
+ if (tokenizer.tryConsumeString()) {
+ while (tokenizer.tryConsumeString()) {}
+ return;
+ }
+ if (!tokenizer.tryConsumeIdentifier() // includes enum & boolean
+ && !tokenizer.tryConsumeInt64() // includes int32
+ && !tokenizer.tryConsumeUInt64() // includes uint32
+ && !tokenizer.tryConsumeDouble()
+ && !tokenizer.tryConsumeFloat()) {
+ throw tokenizer.parseException(
+ "Invalid field value: " + tokenizer.currentToken);
+ }
+ }
+ }
+
+ // =================================================================
+ // Utility functions
+ //
+ // Some of these methods are package-private because Descriptors.java uses
+ // them.
+
+ /**
+ * Escapes bytes in the format used in protocol buffer text format, which
+ * is the same as the format used for C string literals. All bytes
+ * that are not printable 7-bit ASCII characters are escaped, as well as
+ * backslash, single-quote, and double-quote characters. Characters for
+ * which no defined short-hand escape sequence is defined will be escaped
+ * using 3-digit octal sequences.
+ */
+ public static String escapeBytes(ByteString input) {
+ return TextFormatEscaper.escapeBytes(input);
+ }
+
+ /**
+ * Like {@link #escapeBytes(ByteString)}, but used for byte array.
+ */
+ public static String escapeBytes(byte[] input) {
+ return TextFormatEscaper.escapeBytes(input);
+ }
+
+ /**
+ * Un-escape a byte sequence as escaped using
+ * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with
+ * "\x") are also recognized.
+ */
+ public static ByteString unescapeBytes(final CharSequence charString)
+ throws InvalidEscapeSequenceException {
+ // First convert the Java character sequence to UTF-8 bytes.
+ ByteString input = ByteString.copyFromUtf8(charString.toString());
+ // Then unescape certain byte sequences introduced by ASCII '\\'. The valid
+ // escapes can all be expressed with ASCII characters, so it is safe to
+ // operate on bytes here.
+ //
+ // Unescaping the input byte array will result in a byte sequence that's no
+ // longer than the input. That's because each escape sequence is between
+ // two and four bytes long and stands for a single byte.
+ final byte[] result = new byte[input.size()];
+ int pos = 0;
+ for (int i = 0; i < input.size(); i++) {
+ byte c = input.byteAt(i);
+ if (c == '\\') {
+ if (i + 1 < input.size()) {
+ ++i;
+ c = input.byteAt(i);
+ if (isOctal(c)) {
+ // Octal escape.
+ int code = digitValue(c);
+ if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
+ ++i;
+ code = code * 8 + digitValue(input.byteAt(i));
+ }
+ if (i + 1 < input.size() && isOctal(input.byteAt(i + 1))) {
+ ++i;
+ code = code * 8 + digitValue(input.byteAt(i));
+ }
+ // TODO: Check that 0 <= code && code <= 0xFF.
+ result[pos++] = (byte) code;
+ } else {
+ switch (c) {
+ case 'a' : result[pos++] = 0x07; break;
+ case 'b' : result[pos++] = '\b'; break;
+ case 'f' : result[pos++] = '\f'; break;
+ case 'n' : result[pos++] = '\n'; break;
+ case 'r' : result[pos++] = '\r'; break;
+ case 't' : result[pos++] = '\t'; break;
+ case 'v' : result[pos++] = 0x0b; break;
+ case '\\': result[pos++] = '\\'; break;
+ case '\'': result[pos++] = '\''; break;
+ case '"' : result[pos++] = '\"'; break;
+
+ case 'x':
+ // hex escape
+ int code = 0;
+ if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
+ ++i;
+ code = digitValue(input.byteAt(i));
+ } else {
+ throw new InvalidEscapeSequenceException(
+ "Invalid escape sequence: '\\x' with no digits");
+ }
+ if (i + 1 < input.size() && isHex(input.byteAt(i + 1))) {
+ ++i;
+ code = code * 16 + digitValue(input.byteAt(i));
+ }
+ result[pos++] = (byte) code;
+ break;
+
+ default:
+ throw new InvalidEscapeSequenceException(
+ "Invalid escape sequence: '\\" + (char) c + '\'');
+ }
+ }
+ } else {
+ throw new InvalidEscapeSequenceException(
+ "Invalid escape sequence: '\\' at end of string.");
+ }
+ } else {
+ result[pos++] = c;
+ }
+ }
+
+ return result.length == pos
+ ? ByteString.wrap(result) // This reference has not been out of our control.
+ : ByteString.copyFrom(result, 0, pos);
+ }
+
+ /**
+ * Thrown by {@link TextFormat#unescapeBytes} and
+ * {@link TextFormat#unescapeText} when an invalid escape sequence is seen.
+ */
+ public static class InvalidEscapeSequenceException extends IOException {
+ private static final long serialVersionUID = -8164033650142593304L;
+
+ InvalidEscapeSequenceException(final String description) {
+ super(description);
+ }
+ }
+
+ /**
+ * Like {@link #escapeBytes(ByteString)}, but escapes a text string.
+ * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
+ * individually as a 3-digit octal escape. Yes, it's weird.
+ */
+ static String escapeText(final String input) {
+ return escapeBytes(ByteString.copyFromUtf8(input));
+ }
+
+ /**
+ * Escape double quotes and backslashes in a String for unicode output of a message.
+ */
+ public static String escapeDoubleQuotesAndBackslashes(final String input) {
+ return TextFormatEscaper.escapeDoubleQuotesAndBackslashes(input);
+ }
+
+ /**
+ * Un-escape a text string as escaped using {@link #escapeText(String)}.
+ * Two-digit hex escapes (starting with "\x") are also recognized.
+ */
+ static String unescapeText(final String input)
+ throws InvalidEscapeSequenceException {
+ return unescapeBytes(input).toStringUtf8();
+ }
+
+ /** Is this an octal digit? */
+ private static boolean isOctal(final byte c) {
+ return '0' <= c && c <= '7';
+ }
+
+ /** Is this a hex digit? */
+ private static boolean isHex(final byte c) {
+ return ('0' <= c && c <= '9')
+ || ('a' <= c && c <= 'f')
+ || ('A' <= c && c <= 'F');
+ }
+
+ /**
+ * Interpret a character as a digit (in any base up to 36) and return the
+ * numeric value. This is like {@code Character.digit()} but we don't accept
+ * non-ASCII digits.
+ */
+ private static int digitValue(final byte c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ } else if ('a' <= c && c <= 'z') {
+ return c - 'a' + 10;
+ } else {
+ return c - 'A' + 10;
+ }
+ }
+
+ /**
+ * Parse a 32-bit signed integer from the text. Unlike the Java standard
+ * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+ * and "0" to signify hexadecimal and octal numbers, respectively.
+ */
+ static int parseInt32(final String text) throws NumberFormatException {
+ return (int) parseInteger(text, true, false);
+ }
+
+ /**
+ * Parse a 32-bit unsigned integer from the text. Unlike the Java standard
+ * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+ * and "0" to signify hexadecimal and octal numbers, respectively. The
+ * result is coerced to a (signed) {@code int} when returned since Java has
+ * no unsigned integer type.
+ */
+ static int parseUInt32(final String text) throws NumberFormatException {
+ return (int) parseInteger(text, false, false);
+ }
+
+ /**
+ * Parse a 64-bit signed integer from the text. Unlike the Java standard
+ * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+ * and "0" to signify hexadecimal and octal numbers, respectively.
+ */
+ static long parseInt64(final String text) throws NumberFormatException {
+ return parseInteger(text, true, true);
+ }
+
+ /**
+ * Parse a 64-bit unsigned integer from the text. Unlike the Java standard
+ * {@code Integer.parseInt()}, this function recognizes the prefixes "0x"
+ * and "0" to signify hexadecimal and octal numbers, respectively. The
+ * result is coerced to a (signed) {@code long} when returned since Java has
+ * no unsigned long type.
+ */
+ static long parseUInt64(final String text) throws NumberFormatException {
+ return parseInteger(text, false, true);
+ }
+
+ private static long parseInteger(final String text,
+ final boolean isSigned,
+ final boolean isLong)
+ throws NumberFormatException {
+ int pos = 0;
+
+ boolean negative = false;
+ if (text.startsWith("-", pos)) {
+ if (!isSigned) {
+ throw new NumberFormatException("Number must be positive: " + text);
+ }
+ ++pos;
+ negative = true;
+ }
+
+ int radix = 10;
+ if (text.startsWith("0x", pos)) {
+ pos += 2;
+ radix = 16;
+ } else if (text.startsWith("0", pos)) {
+ radix = 8;
+ }
+
+ final String numberText = text.substring(pos);
+
+ long result = 0;
+ if (numberText.length() < 16) {
+ // Can safely assume no overflow.
+ result = Long.parseLong(numberText, radix);
+ if (negative) {
+ result = -result;
+ }
+
+ // Check bounds.
+ // No need to check for 64-bit numbers since they'd have to be 16 chars
+ // or longer to overflow.
+ if (!isLong) {
+ if (isSigned) {
+ if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) {
+ throw new NumberFormatException(
+ "Number out of range for 32-bit signed integer: " + text);
+ }
+ } else {
+ if (result >= (1L << 32) || result < 0) {
+ throw new NumberFormatException(
+ "Number out of range for 32-bit unsigned integer: " + text);
+ }
+ }
+ }
+ } else {
+ BigInteger bigValue = new BigInteger(numberText, radix);
+ if (negative) {
+ bigValue = bigValue.negate();
+ }
+
+ // Check bounds.
+ if (!isLong) {
+ if (isSigned) {
+ if (bigValue.bitLength() > 31) {
+ throw new NumberFormatException(
+ "Number out of range for 32-bit signed integer: " + text);
+ }
+ } else {
+ if (bigValue.bitLength() > 32) {
+ throw new NumberFormatException(
+ "Number out of range for 32-bit unsigned integer: " + text);
+ }
+ }
+ } else {
+ if (isSigned) {
+ if (bigValue.bitLength() > 63) {
+ throw new NumberFormatException(
+ "Number out of range for 64-bit signed integer: " + text);
+ }
+ } else {
+ if (bigValue.bitLength() > 64) {
+ throw new NumberFormatException(
+ "Number out of range for 64-bit unsigned integer: " + text);
+ }
+ }
+ }
+
+ result = bigValue.longValue();
+ }
+
+ return result;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java
new file mode 100644
index 0000000000..da9ceadd16
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java
@@ -0,0 +1,137 @@
+// 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;
+
+/**
+ * Provide text format escaping support for proto2 instances.
+ */
+final class TextFormatEscaper {
+ private TextFormatEscaper() {}
+
+ private interface ByteSequence {
+ int size();
+ byte byteAt(int offset);
+ }
+
+ /**
+ * Escapes bytes in the format used in protocol buffer text format, which
+ * is the same as the format used for C string literals. All bytes
+ * that are not printable 7-bit ASCII characters are escaped, as well as
+ * backslash, single-quote, and double-quote characters. Characters for
+ * which no defined short-hand escape sequence is defined will be escaped
+ * using 3-digit octal sequences.
+ */
+ static String escapeBytes(final ByteSequence input) {
+ final StringBuilder builder = new StringBuilder(input.size());
+ for (int i = 0; i < input.size(); i++) {
+ final byte b = input.byteAt(i);
+ switch (b) {
+ // Java does not recognize \a or \v, apparently.
+ case 0x07: builder.append("\\a"); break;
+ case '\b': builder.append("\\b"); break;
+ case '\f': builder.append("\\f"); break;
+ case '\n': builder.append("\\n"); break;
+ case '\r': builder.append("\\r"); break;
+ case '\t': builder.append("\\t"); break;
+ case 0x0b: builder.append("\\v"); break;
+ case '\\': builder.append("\\\\"); break;
+ case '\'': builder.append("\\\'"); break;
+ case '"' : builder.append("\\\""); break;
+ default:
+ // Only ASCII characters between 0x20 (space) and 0x7e (tilde) are
+ // printable. Other byte values must be escaped.
+ if (b >= 0x20 && b <= 0x7e) {
+ builder.append((char) b);
+ } else {
+ builder.append('\\');
+ builder.append((char) ('0' + ((b >>> 6) & 3)));
+ builder.append((char) ('0' + ((b >>> 3) & 7)));
+ builder.append((char) ('0' + (b & 7)));
+ }
+ break;
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Escapes bytes in the format used in protocol buffer text format, which
+ * is the same as the format used for C string literals. All bytes
+ * that are not printable 7-bit ASCII characters are escaped, as well as
+ * backslash, single-quote, and double-quote characters. Characters for
+ * which no defined short-hand escape sequence is defined will be escaped
+ * using 3-digit octal sequences.
+ */
+ static String escapeBytes(final ByteString input) {
+ return escapeBytes(new ByteSequence() {
+ @Override
+ public int size() {
+ return input.size();
+ }
+ @Override
+ public byte byteAt(int offset) {
+ return input.byteAt(offset);
+ }
+ });
+ }
+
+ /**
+ * Like {@link #escapeBytes(ByteString)}, but used for byte array.
+ */
+ static String escapeBytes(final byte[] input) {
+ return escapeBytes(new ByteSequence() {
+ @Override
+ public int size() {
+ return input.length;
+ }
+ @Override
+ public byte byteAt(int offset) {
+ return input[offset];
+ }
+ });
+ }
+
+ /**
+ * Like {@link #escapeBytes(ByteString)}, but escapes a text string.
+ * Non-ASCII characters are first encoded as UTF-8, then each byte is escaped
+ * individually as a 3-digit octal escape. Yes, it's weird.
+ */
+ static String escapeText(final String input) {
+ return escapeBytes(ByteString.copyFromUtf8(input));
+ }
+
+ /**
+ * Escape double quotes and backslashes in a String for unicode output of a message.
+ */
+ static String escapeDoubleQuotesAndBackslashes(final String input) {
+ return input.replace("\\", "\\\\").replace("\"", "\\\"");
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
new file mode 100644
index 0000000000..0127ce92a3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java
@@ -0,0 +1,226 @@
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+
+/**
+ * Data structure which is populated with the locations of each field value parsed from the text.
+ *
+ * <p>The locations of primary fields values are retrieved by {@code getLocation} or
+ * {@code getLocations}. The locations of sub message values are within nested
+ * {@code TextFormatParseInfoTree}s and are retrieve by {@code getNestedTree} or
+ * {@code getNestedTrees}.
+ *
+ * <p>The {@code TextFormatParseInfoTree} is created by a Builder.
+ */
+public class TextFormatParseInfoTree {
+
+ // Defines a mapping between each field's descriptor to the list of locations where
+ // its value(s) were was encountered.
+ private Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField;
+
+ // Defines a mapping between a field's descriptor to a list of TextFormatParseInfoTrees for
+ // sub message location information.
+ Map<FieldDescriptor, List<TextFormatParseInfoTree>> subtreesFromField;
+
+ /**
+ * Construct a {@code TextFormatParseInfoTree}.
+ *
+ * @param locationsFromField a map of fields to location in the source code
+ * @param subtreeBuildersFromField a map of fields to parse tree location information builders
+ */
+ private TextFormatParseInfoTree(
+ Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField,
+ Map<FieldDescriptor, List<TextFormatParseInfoTree.Builder>> subtreeBuildersFromField) {
+
+ // The maps are unmodifiable. The values in the maps are unmodifiable.
+ Map<FieldDescriptor, List<TextFormatParseLocation>> locs =
+ new HashMap<FieldDescriptor, List<TextFormatParseLocation>>();
+ for (Entry<FieldDescriptor, List<TextFormatParseLocation>> kv : locationsFromField.entrySet()) {
+ locs.put(kv.getKey(), Collections.unmodifiableList(kv.getValue()));
+ }
+ this.locationsFromField = Collections.unmodifiableMap(locs);
+
+ Map<FieldDescriptor, List<TextFormatParseInfoTree>> subs =
+ new HashMap<FieldDescriptor, List<TextFormatParseInfoTree>>();
+ for (Entry<FieldDescriptor, List<Builder>> kv : subtreeBuildersFromField.entrySet()) {
+ List<TextFormatParseInfoTree> submessagesOfField = new ArrayList<TextFormatParseInfoTree>();
+ for (Builder subBuilder : kv.getValue()) {
+ submessagesOfField.add(subBuilder.build());
+ }
+ subs.put(kv.getKey(), Collections.unmodifiableList(submessagesOfField));
+ }
+ this.subtreesFromField = Collections.unmodifiableMap(subs);
+ }
+
+ /**
+ * Retrieve all the locations of a field.
+ *
+ * @param fieldDescriptor the the @{link FieldDescriptor} of the desired field
+ * @return a list of the locations of values of the field. If there are not values
+ * or the field doesn't exist, an empty list is returned.
+ */
+ public List<TextFormatParseLocation> getLocations(final FieldDescriptor fieldDescriptor) {
+ List<TextFormatParseLocation> result = locationsFromField.get(fieldDescriptor);
+ return (result == null) ? Collections.<TextFormatParseLocation>emptyList() : result;
+ }
+
+ /**
+ * Get the location in the source of a field's value.
+ *
+ * <p>Returns the {@link TextFormatParseLocation} for index-th value of the field in the parsed
+ * text.
+ *
+ * @param fieldDescriptor the @{link FieldDescriptor} of the desired field
+ * @param index the index of the value.
+ * @return the {@link TextFormatParseLocation} of the value
+ * @throws IllegalArgumentException index is out of range
+ */
+ public TextFormatParseLocation getLocation(final FieldDescriptor fieldDescriptor, int index) {
+ return getFromList(getLocations(fieldDescriptor), index, fieldDescriptor);
+ }
+
+ /**
+ * Retrieve a list of all the location information trees for a sub message field.
+ *
+ * @param fieldDescriptor the @{link FieldDescriptor} of the desired field
+ * @return A list of {@link TextFormatParseInfoTree}
+ */
+ public List<TextFormatParseInfoTree> getNestedTrees(final FieldDescriptor fieldDescriptor) {
+ List<TextFormatParseInfoTree> result = subtreesFromField.get(fieldDescriptor);
+ return result == null ? Collections.<TextFormatParseInfoTree>emptyList() : result;
+ }
+
+ /**
+ * Returns the parse info tree for the given field, which must be a message type.
+ *
+ * @param fieldDescriptor the @{link FieldDescriptor} of the desired sub message
+ * @param index the index of message value.
+ * @return the {@code ParseInfoTree} of the message value. {@code null} is returned if the field
+ * doesn't exist or the index is out of range.
+ * @throws IllegalArgumentException if index is out of range
+ */
+ public TextFormatParseInfoTree getNestedTree(final FieldDescriptor fieldDescriptor, int index) {
+ return getFromList(getNestedTrees(fieldDescriptor), index, fieldDescriptor);
+ }
+
+ /**
+ * Create a builder for a {@code ParseInfoTree}.
+ *
+ * @return the builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private static <T> T getFromList(List<T> list, int index, FieldDescriptor fieldDescriptor) {
+ if (index >= list.size() || index < 0) {
+ throw new IllegalArgumentException(String.format("Illegal index field: %s, index %d",
+ fieldDescriptor == null ? "<null>" : fieldDescriptor.getName(), index));
+ }
+ return list.get(index);
+ }
+
+ /**
+ * Builder for a {@link TextFormatParseInfoTree}.
+ */
+ public static class Builder {
+
+ private Map<FieldDescriptor, List<TextFormatParseLocation>> locationsFromField;
+
+ // Defines a mapping between a field's descriptor to a list of ParseInfoTrees builders for
+ // sub message location information.
+ private Map<FieldDescriptor, List<Builder>> subtreeBuildersFromField;
+
+ /**
+ * Create a root level {@ParseInfoTree} builder.
+ */
+ private Builder() {
+ locationsFromField = new HashMap<FieldDescriptor, List<TextFormatParseLocation>>();
+ subtreeBuildersFromField = new HashMap<FieldDescriptor, List<Builder>>();
+ }
+
+ /**
+ * Record the starting location of a single value for a field.
+ *
+ * @param fieldDescriptor the field
+ * @param location source code location information
+ */
+ public Builder setLocation(
+ final FieldDescriptor fieldDescriptor, TextFormatParseLocation location) {
+ List<TextFormatParseLocation> fieldLocations = locationsFromField.get(fieldDescriptor);
+ if (fieldLocations == null) {
+ fieldLocations = new ArrayList<TextFormatParseLocation>();
+ locationsFromField.put(fieldDescriptor, fieldLocations);
+ }
+ fieldLocations.add(location);
+ return this;
+ }
+
+ /**
+ * Set for a sub message.
+ *
+ * <p>A new builder is created for a sub message. The builder that is returned is a new builder.
+ * The return is <em>not</em> the invoked {@code builder.getBuilderForSubMessageField}.
+ *
+ * @param fieldDescriptor the field whose value is the submessage
+ * @return a new Builder for the sub message
+ */
+ public Builder getBuilderForSubMessageField(final FieldDescriptor fieldDescriptor) {
+ List<Builder> submessageBuilders = subtreeBuildersFromField.get(fieldDescriptor);
+ if (submessageBuilders == null) {
+ submessageBuilders = new ArrayList<Builder>();
+ subtreeBuildersFromField.put(fieldDescriptor, submessageBuilders);
+ }
+ Builder subtreeBuilder = new Builder();
+ submessageBuilders.add(subtreeBuilder);
+ return subtreeBuilder;
+ }
+
+ /**
+ * Build the {@code TextFormatParseInfoTree}.
+ *
+ * @return the {@code TextFormatParseInfoTree}
+ */
+ public TextFormatParseInfoTree build() {
+ return new TextFormatParseInfoTree(locationsFromField, subtreeBuildersFromField);
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java
new file mode 100644
index 0000000000..cce286e10f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java
@@ -0,0 +1,104 @@
+// 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.util.Arrays;
+
+/**
+ * A location in the source code.
+ *
+ * <p>A location is the starting line number and starting column number.
+ */
+public final class TextFormatParseLocation {
+
+ /**
+ * The empty location.
+ */
+ public static final TextFormatParseLocation EMPTY = new TextFormatParseLocation(-1, -1);
+
+ /**
+ * Create a location.
+ *
+ * @param line the starting line number
+ * @param column the starting column number
+ * @return a {@code ParseLocation}
+ */
+ static TextFormatParseLocation create(int line, int column) {
+ if (line == -1 && column == -1) {
+ return EMPTY;
+ }
+ if (line < 0 || column < 0) {
+ throw new IllegalArgumentException(
+ String.format("line and column values must be >= 0: line %d, column: %d", line, column));
+ }
+ return new TextFormatParseLocation(line, column);
+ }
+
+ private final int line;
+ private final int column;
+
+ private TextFormatParseLocation(int line, int column) {
+ this.line = line;
+ this.column = column;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ParseLocation{line=%d, column=%d}", line, column);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof TextFormatParseLocation)) {
+ return false;
+ }
+ TextFormatParseLocation that = (TextFormatParseLocation) o;
+ return (this.line == that.getLine())
+ && (this.column == that.getColumn());
+ }
+
+ @Override
+ public int hashCode() {
+ int[] values = {line, column};
+ return Arrays.hashCode(values);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java
new file mode 100644
index 0000000000..5714c063a9
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java
@@ -0,0 +1,99 @@
+// 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.util.Collections;
+import java.util.List;
+
+/**
+ * Thrown when attempting to build a protocol message that is missing required
+ * fields. This is a {@code RuntimeException} because it normally represents
+ * a programming error: it happens when some code which constructs a message
+ * fails to set all the fields. {@code parseFrom()} methods <b>do not</b>
+ * throw this; they throw an {@link InvalidProtocolBufferException} if
+ * required fields are missing, because it is not a programming error to
+ * receive an incomplete message. In other words,
+ * {@code UninitializedMessageException} should never be thrown by correct
+ * code, but {@code InvalidProtocolBufferException} might be.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class UninitializedMessageException extends RuntimeException {
+ private static final long serialVersionUID = -7466929953374883507L;
+
+ public UninitializedMessageException(final MessageLite message) {
+ super("Message was missing required fields. (Lite runtime could not " +
+ "determine which fields were missing).");
+ missingFields = null;
+ }
+
+ public UninitializedMessageException(final List<String> missingFields) {
+ super(buildDescription(missingFields));
+ this.missingFields = missingFields;
+ }
+
+ private final List<String> missingFields;
+
+ /**
+ * Get a list of human-readable names of required fields missing from this
+ * message. Each name is a full path to a field, e.g. "foo.bar[5].baz".
+ * Returns null if the lite runtime was used, since it lacks the ability to
+ * find missing fields.
+ */
+ public List<String> getMissingFields() {
+ return Collections.unmodifiableList(missingFields);
+ }
+
+ /**
+ * Converts this exception to an {@link InvalidProtocolBufferException}.
+ * When a parsed message is missing required fields, this should be thrown
+ * instead of {@code UninitializedMessageException}.
+ */
+ public InvalidProtocolBufferException asInvalidProtocolBufferException() {
+ return new InvalidProtocolBufferException(getMessage());
+ }
+
+ /** Construct the description string for this exception. */
+ private static String buildDescription(final List<String> missingFields) {
+ final StringBuilder description =
+ new StringBuilder("Message missing required fields: ");
+ boolean first = true;
+ for (final String field : missingFields) {
+ if (first) {
+ first = false;
+ } else {
+ description.append(", ");
+ }
+ description.append(field);
+ }
+ return description.toString();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
new file mode 100644
index 0000000000..2bef27e923
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -0,0 +1,1042 @@
+// 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 com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * {@code UnknownFieldSet} is used to keep track of fields which were seen when
+ * parsing a protocol message but whose field numbers or types are unrecognized.
+ * This most frequently occurs when new fields are added to a message type
+ * and then messages containing those fields are read by old software that was
+ * compiled before the new types were added.
+ *
+ * <p>Every {@link Message} contains an {@code UnknownFieldSet} (and every
+ * {@link Message.Builder} contains an {@link Builder}).
+ *
+ * <p>Most users will never need to use this class.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class UnknownFieldSet implements MessageLite {
+
+ private UnknownFieldSet() {
+ fields = null;
+ }
+
+ /** Create a new {@link Builder}. */
+ public static Builder newBuilder() {
+ return Builder.create();
+ }
+
+ /**
+ * Create a new {@link Builder} and initialize it to be a copy
+ * of {@code copyFrom}.
+ */
+ public static Builder newBuilder(final UnknownFieldSet copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
+ }
+
+ /** Get an empty {@code UnknownFieldSet}. */
+ public static UnknownFieldSet getDefaultInstance() {
+ return defaultInstance;
+ }
+ @Override
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+ private static final UnknownFieldSet defaultInstance =
+ new UnknownFieldSet(Collections.<Integer, Field>emptyMap(),
+ Collections.<Integer, Field>emptyMap());
+
+ /**
+ * Construct an {@code UnknownFieldSet} around the given map. The map is
+ * expected to be immutable.
+ */
+ private UnknownFieldSet(final Map<Integer, Field> fields,
+ final Map<Integer, Field> fieldsDescending) {
+ this.fields = fields;
+ }
+ private final Map<Integer, Field> fields;
+
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ return (other instanceof UnknownFieldSet) &&
+ fields.equals(((UnknownFieldSet) other).fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return fields.hashCode();
+ }
+
+ /** Get a map of fields in the set by number. */
+ public Map<Integer, Field> asMap() {
+ return fields;
+ }
+
+ /** Check if the given field number is present in the set. */
+ public boolean hasField(final int number) {
+ return fields.containsKey(number);
+ }
+
+ /**
+ * Get a field by number. Returns an empty field if not present. Never
+ * returns {@code null}.
+ */
+ public Field getField(final int number) {
+ final Field result = fields.get(number);
+ return (result == null) ? Field.getDefaultInstance() : result;
+ }
+
+ /** Serializes the set and writes it to {@code output}. */
+ @Override
+ public void writeTo(final CodedOutputStream output) throws IOException {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ Field field = entry.getValue();
+ field.writeTo(entry.getKey(), output);
+ }
+ }
+
+ /**
+ * Converts the set to a string in protocol buffer text format. This is
+ * just a trivial wrapper around
+ * {@link TextFormat#printToString(UnknownFieldSet)}.
+ */
+ @Override
+ public String toString() {
+ return TextFormat.printToString(this);
+ }
+
+ /**
+ * Serializes the message to a {@code ByteString} and returns it. This is
+ * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ @Override
+ public ByteString toByteString() {
+ try {
+ final ByteString.CodedBuilder out =
+ ByteString.newCodedBuilder(getSerializedSize());
+ writeTo(out.getCodedOutput());
+ return out.build();
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Serializing to a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Serializes the message to a {@code byte} array and returns it. This is
+ * just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ @Override
+ public byte[] toByteArray() {
+ try {
+ final byte[] result = new byte[getSerializedSize()];
+ final CodedOutputStream output = CodedOutputStream.newInstance(result);
+ writeTo(output);
+ output.checkNoSpaceLeft();
+ return result;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Serializing to a byte array threw an IOException " +
+ "(should never happen).", e);
+ }
+ }
+
+ /**
+ * Serializes the message and writes it to {@code output}. This is just a
+ * trivial wrapper around {@link #writeTo(CodedOutputStream)}.
+ */
+ @Override
+ public void writeTo(final OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ @Override
+ public void writeDelimitedTo(OutputStream output) throws IOException {
+ final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ codedOutput.writeRawVarint32(getSerializedSize());
+ writeTo(codedOutput);
+ codedOutput.flush();
+ }
+
+ /** Get the number of bytes required to encode this set. */
+ @Override
+ public int getSerializedSize() {
+ int result = 0;
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ result += entry.getValue().getSerializedSize(entry.getKey());
+ }
+ return result;
+ }
+
+ /**
+ * Serializes the set and writes it to {@code output} using
+ * {@code MessageSet} wire format.
+ */
+ public void writeAsMessageSetTo(final CodedOutputStream output)
+ throws IOException {
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ entry.getValue().writeAsMessageSetExtensionTo(
+ entry.getKey(), output);
+ }
+ }
+
+
+ /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */
+ public int getSerializedSizeAsMessageSet() {
+ int result = 0;
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ result += entry.getValue().getSerializedSizeAsMessageSetExtension(
+ entry.getKey());
+ }
+ return result;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
+
+ /** Parse an {@code UnknownFieldSet} from the given input stream. */
+ public static UnknownFieldSet parseFrom(final CodedInputStream input)
+ throws IOException {
+ return newBuilder().mergeFrom(input).build();
+ }
+
+ /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+ public static UnknownFieldSet parseFrom(final ByteString data)
+ throws InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).build();
+ }
+
+ /** Parse {@code data} as an {@code UnknownFieldSet} and return it. */
+ public static UnknownFieldSet parseFrom(final byte[] data)
+ throws InvalidProtocolBufferException {
+ return newBuilder().mergeFrom(data).build();
+ }
+
+ /** Parse an {@code UnknownFieldSet} from {@code input} and return it. */
+ public static UnknownFieldSet parseFrom(final InputStream input)
+ throws IOException {
+ return newBuilder().mergeFrom(input).build();
+ }
+
+ @Override
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return newBuilder().mergeFrom(this);
+ }
+
+ /**
+ * Builder for {@link UnknownFieldSet}s.
+ *
+ * <p>Note that this class maintains {@link Field.Builder}s for all fields
+ * in the set. Thus, adding one element to an existing {@link Field} does not
+ * require making a copy. This is important for efficient parsing of
+ * unknown repeated fields. However, it implies that {@link Field}s cannot
+ * be constructed independently, nor can two {@link UnknownFieldSet}s share
+ * the same {@code Field} object.
+ *
+ * <p>Use {@link UnknownFieldSet#newBuilder()} to construct a {@code Builder}.
+ */
+ public static final class Builder implements MessageLite.Builder {
+ // This constructor should never be called directly (except from 'create').
+ private Builder() {}
+
+ private Map<Integer, Field> fields;
+
+ // Optimization: We keep around a builder for the last field that was
+ // modified so that we can efficiently add to it multiple times in a
+ // row (important when parsing an unknown repeated field).
+ private int lastFieldNumber;
+ private Field.Builder lastField;
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.reinitialize();
+ return builder;
+ }
+
+ /**
+ * Get a field builder for the given field number which includes any
+ * values that already exist.
+ */
+ private Field.Builder getFieldBuilder(final int number) {
+ if (lastField != null) {
+ if (number == lastFieldNumber) {
+ return lastField;
+ }
+ // Note: addField() will reset lastField and lastFieldNumber.
+ addField(lastFieldNumber, lastField.build());
+ }
+ if (number == 0) {
+ return null;
+ } else {
+ final Field existing = fields.get(number);
+ lastFieldNumber = number;
+ lastField = Field.newBuilder();
+ if (existing != null) {
+ lastField.mergeFrom(existing);
+ }
+ return lastField;
+ }
+ }
+
+ /**
+ * Build the {@link UnknownFieldSet} and return it.
+ *
+ * <p>Once {@code build()} has been called, the {@code Builder} will no
+ * longer be usable. Calling any method after {@code build()} will result
+ * in undefined behavior and can cause a {@code NullPointerException} to be
+ * thrown.
+ */
+ @Override
+ public UnknownFieldSet build() {
+ getFieldBuilder(0); // Force lastField to be built.
+ final UnknownFieldSet result;
+ if (fields.isEmpty()) {
+ result = getDefaultInstance();
+ } else {
+ Map<Integer, Field> descendingFields = null;
+ result = new UnknownFieldSet(Collections.unmodifiableMap(fields), descendingFields);
+ }
+ fields = null;
+ return result;
+ }
+
+ @Override
+ public UnknownFieldSet buildPartial() {
+ // No required fields, so this is the same as build().
+ return build();
+ }
+
+ @Override
+ public Builder clone() {
+ getFieldBuilder(0); // Force lastField to be built.
+ Map<Integer, Field> descendingFields = null;
+ return UnknownFieldSet.newBuilder().mergeFrom(
+ new UnknownFieldSet(fields, descendingFields));
+ }
+
+ @Override
+ public UnknownFieldSet getDefaultInstanceForType() {
+ return UnknownFieldSet.getDefaultInstance();
+ }
+
+ private void reinitialize() {
+ fields = Collections.emptyMap();
+ lastFieldNumber = 0;
+ lastField = null;
+ }
+
+ /** Reset the builder to an empty set. */
+ @Override
+ public Builder clear() {
+ reinitialize();
+ return this;
+ }
+
+ /** Clear fields from the set with a given field number. */
+ public Builder clearField(final int number) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ if (lastField != null && lastFieldNumber == number) {
+ // Discard this.
+ lastField = null;
+ lastFieldNumber = 0;
+ }
+ if (fields.containsKey(number)) {
+ fields.remove(number);
+ }
+ return this;
+ }
+
+ /**
+ * Merge the fields from {@code other} into this set. If a field number
+ * exists in both sets, {@code other}'s values for that field will be
+ * appended to the values in this set.
+ */
+ public Builder mergeFrom(final UnknownFieldSet other) {
+ if (other != getDefaultInstance()) {
+ for (final Map.Entry<Integer, Field> entry : other.fields.entrySet()) {
+ mergeField(entry.getKey(), entry.getValue());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Add a field to the {@code UnknownFieldSet}. If a field with the same
+ * number already exists, the two are merged.
+ */
+ public Builder mergeField(final int number, final Field field) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ if (hasField(number)) {
+ getFieldBuilder(number).mergeFrom(field);
+ } else {
+ // Optimization: We could call getFieldBuilder(number).mergeFrom(field)
+ // in this case, but that would create a copy of the Field object.
+ // We'd rather reuse the one passed to us, so call addField() instead.
+ addField(number, field);
+ }
+ return this;
+ }
+
+ /**
+ * Convenience method for merging a new field containing a single varint
+ * value. This is used in particular when an unknown enum value is
+ * encountered.
+ */
+ public Builder mergeVarintField(final int number, final int value) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ getFieldBuilder(number).addVarint(value);
+ return this;
+ }
+
+
+ /**
+ * Convenience method for merging a length-delimited field.
+ *
+ * <p>For use by generated code only.
+ */
+ public Builder mergeLengthDelimitedField(
+ final int number, final ByteString value) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ getFieldBuilder(number).addLengthDelimited(value);
+ return this;
+ }
+
+ /** Check if the given field number is present in the set. */
+ public boolean hasField(final int number) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ return number == lastFieldNumber || fields.containsKey(number);
+ }
+
+ /**
+ * Add a field to the {@code UnknownFieldSet}. If a field with the same
+ * number already exists, it is removed.
+ */
+ public Builder addField(final int number, final Field field) {
+ if (number == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+ if (lastField != null && lastFieldNumber == number) {
+ // Discard this.
+ lastField = null;
+ lastFieldNumber = 0;
+ }
+ if (fields.isEmpty()) {
+ fields = new TreeMap<Integer,Field>();
+ }
+ fields.put(number, field);
+ return this;
+ }
+
+ /**
+ * Get all present {@code Field}s as an immutable {@code Map}. If more
+ * fields are added, the changes may or may not be reflected in this map.
+ */
+ public Map<Integer, Field> asMap() {
+ getFieldBuilder(0); // Force lastField to be built.
+ return Collections.unmodifiableMap(fields);
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ @Override
+ public Builder mergeFrom(final CodedInputStream input) throws IOException {
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Parse a single field from {@code input} and merge it into this set.
+ * @param tag The field's tag number, which was already parsed.
+ * @return {@code false} if the tag is an end group tag.
+ */
+ public boolean mergeFieldFrom(final int tag, final CodedInputStream input)
+ throws IOException {
+ final int number = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ getFieldBuilder(number).addVarint(input.readInt64());
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ getFieldBuilder(number).addFixed64(input.readFixed64());
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ getFieldBuilder(number).addLengthDelimited(input.readBytes());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final Builder subBuilder = newBuilder();
+ input.readGroup(number, subBuilder,
+ ExtensionRegistry.getEmptyRegistry());
+ getFieldBuilder(number).addGroup(subBuilder.build());
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ case WireFormat.WIRETYPE_FIXED32:
+ getFieldBuilder(number).addFixed32(input.readFixed32());
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ /**
+ * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ @Override
+ public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = data.newCodedInput();
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (final InvalidProtocolBufferException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Reading from a ByteString threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Parse {@code data} as an {@code UnknownFieldSet} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ @Override
+ public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input = CodedInputStream.newInstance(data);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (final InvalidProtocolBufferException e) {
+ throw e;
+ } catch (final IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ /**
+ * Parse an {@code UnknownFieldSet} from {@code input} and merge it with the
+ * set being built. This is just a small wrapper around
+ * {@link #mergeFrom(CodedInputStream)}.
+ */
+ @Override
+ public Builder mergeFrom(final InputStream input) throws IOException {
+ final CodedInputStream codedInput = CodedInputStream.newInstance(input);
+ mergeFrom(codedInput);
+ codedInput.checkLastTagWas(0);
+ return this;
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(InputStream input) throws IOException {
+ final int firstByte = input.read();
+ if (firstByte == -1) {
+ return false;
+ }
+ final int size = CodedInputStream.readRawVarint32(firstByte, input);
+ final InputStream limitedInput = new LimitedInputStream(input, size);
+ mergeFrom(limitedInput);
+ return true;
+ }
+
+ @Override
+ public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeDelimitedFrom(input);
+ }
+
+ @Override
+ public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ @Override
+ public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data);
+ }
+
+ @Override
+ public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException {
+ try {
+ final CodedInputStream input =
+ CodedInputStream.newInstance(data, off, len);
+ mergeFrom(input);
+ input.checkLastTagWas(0);
+ return this;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Reading from a byte array threw an IOException (should " +
+ "never happen).", e);
+ }
+ }
+
+ @Override
+ public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data);
+ }
+
+ @Override
+ public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(data, off, len);
+ }
+
+ @Override
+ public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ // UnknownFieldSet has no extensions.
+ return mergeFrom(input);
+ }
+
+ @Override
+ public Builder mergeFrom(MessageLite m) {
+ if (m instanceof UnknownFieldSet) {
+ return mergeFrom((UnknownFieldSet) m);
+ }
+ throw new IllegalArgumentException(
+ "mergeFrom(MessageLite) can only merge messages of the same type.");
+ }
+
+ @Override
+ public boolean isInitialized() {
+ // UnknownFieldSets do not have required fields, so they are always
+ // initialized.
+ return true;
+ }
+ }
+
+ /**
+ * Represents a single field in an {@code UnknownFieldSet}.
+ *
+ * <p>A {@code Field} consists of five lists of values. The lists correspond
+ * to the five "wire types" used in the protocol buffer binary format.
+ * The wire type of each field can be determined from the encoded form alone,
+ * without knowing the field's declared type. So, we are able to parse
+ * unknown values at least this far and separate them. Normally, only one
+ * of the five lists will contain any values, since it is impossible to
+ * define a valid message type that declares two different types for the
+ * same field number. However, the code is designed to allow for the case
+ * where the same unknown field number is encountered using multiple different
+ * wire types.
+ *
+ * <p>{@code Field} is an immutable class. To construct one, you must use a
+ * {@link Builder}.
+ *
+ * @see UnknownFieldSet
+ */
+ public static final class Field {
+ private Field() {}
+
+ /** Construct a new {@link Builder}. */
+ public static Builder newBuilder() {
+ return Builder.create();
+ }
+
+ /**
+ * Construct a new {@link Builder} and initialize it to a copy of
+ * {@code copyFrom}.
+ */
+ public static Builder newBuilder(final Field copyFrom) {
+ return newBuilder().mergeFrom(copyFrom);
+ }
+
+ /** Get an empty {@code Field}. */
+ public static Field getDefaultInstance() {
+ return fieldDefaultInstance;
+ }
+ private static final Field fieldDefaultInstance = newBuilder().build();
+
+ /** Get the list of varint values for this field. */
+ public List<Long> getVarintList() { return varint; }
+
+ /** Get the list of fixed32 values for this field. */
+ public List<Integer> getFixed32List() { return fixed32; }
+
+ /** Get the list of fixed64 values for this field. */
+ public List<Long> getFixed64List() { return fixed64; }
+
+ /** Get the list of length-delimited values for this field. */
+ public List<ByteString> getLengthDelimitedList() { return lengthDelimited; }
+
+ /**
+ * Get the list of embedded group values for this field. These are
+ * represented using {@link UnknownFieldSet}s rather than {@link Message}s
+ * since the group's type is presumably unknown.
+ */
+ public List<UnknownFieldSet> getGroupList() { return group; }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Field)) {
+ return false;
+ }
+ return Arrays.equals(getIdentityArray(),
+ ((Field) other).getIdentityArray());
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(getIdentityArray());
+ }
+
+ /**
+ * Returns the array of objects to be used to uniquely identify this
+ * {@link Field} instance.
+ */
+ private Object[] getIdentityArray() {
+ return new Object[] {
+ varint,
+ fixed32,
+ fixed64,
+ lengthDelimited,
+ group};
+ }
+
+ /**
+ * Serializes the field, including field number, and writes it to
+ * {@code output}.
+ */
+ public void writeTo(final int fieldNumber, final CodedOutputStream output)
+ throws IOException {
+ for (final long value : varint) {
+ output.writeUInt64(fieldNumber, value);
+ }
+ for (final int value : fixed32) {
+ output.writeFixed32(fieldNumber, value);
+ }
+ for (final long value : fixed64) {
+ output.writeFixed64(fieldNumber, value);
+ }
+ for (final ByteString value : lengthDelimited) {
+ output.writeBytes(fieldNumber, value);
+ }
+ for (final UnknownFieldSet value : group) {
+ output.writeGroup(fieldNumber, value);
+ }
+ }
+
+ /**
+ * Get the number of bytes required to encode this field, including field
+ * number.
+ */
+ public int getSerializedSize(final int fieldNumber) {
+ int result = 0;
+ for (final long value : varint) {
+ result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
+ }
+ for (final int value : fixed32) {
+ result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
+ }
+ for (final long value : fixed64) {
+ result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
+ }
+ for (final ByteString value : lengthDelimited) {
+ result += CodedOutputStream.computeBytesSize(fieldNumber, value);
+ }
+ for (final UnknownFieldSet value : group) {
+ result += CodedOutputStream.computeGroupSize(fieldNumber, value);
+ }
+ return result;
+ }
+
+ /**
+ * Serializes the field, including field number, and writes it to
+ * {@code output}, using {@code MessageSet} wire format.
+ */
+ public void writeAsMessageSetExtensionTo(
+ final int fieldNumber,
+ final CodedOutputStream output)
+ throws IOException {
+ for (final ByteString value : lengthDelimited) {
+ output.writeRawMessageSetExtension(fieldNumber, value);
+ }
+ }
+
+
+ /**
+ * Get the number of bytes required to encode this field, including field number, using {@code
+ * MessageSet} wire format.
+ */
+ public int getSerializedSizeAsMessageSetExtension(final int fieldNumber) {
+ int result = 0;
+ for (final ByteString value : lengthDelimited) {
+ result += CodedOutputStream.computeRawMessageSetExtensionSize(
+ fieldNumber, value);
+ }
+ return result;
+ }
+
+ private List<Long> varint;
+ private List<Integer> fixed32;
+ private List<Long> fixed64;
+ private List<ByteString> lengthDelimited;
+ private List<UnknownFieldSet> group;
+
+ /**
+ * Used to build a {@link Field} within an {@link UnknownFieldSet}.
+ *
+ * <p>Use {@link Field#newBuilder()} to construct a {@code Builder}.
+ */
+ public static final class Builder {
+ // This constructor should never be called directly (except from 'create').
+ private Builder() {}
+
+ private static Builder create() {
+ Builder builder = new Builder();
+ builder.result = new Field();
+ return builder;
+ }
+
+ private Field result;
+
+ /**
+ * Build the field. After {@code build()} has been called, the
+ * {@code Builder} is no longer usable. Calling any other method will
+ * result in undefined behavior and can cause a
+ * {@code NullPointerException} to be thrown.
+ */
+ public Field build() {
+ if (result.varint == null) {
+ result.varint = Collections.emptyList();
+ } else {
+ result.varint = Collections.unmodifiableList(result.varint);
+ }
+ if (result.fixed32 == null) {
+ result.fixed32 = Collections.emptyList();
+ } else {
+ result.fixed32 = Collections.unmodifiableList(result.fixed32);
+ }
+ if (result.fixed64 == null) {
+ result.fixed64 = Collections.emptyList();
+ } else {
+ result.fixed64 = Collections.unmodifiableList(result.fixed64);
+ }
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = Collections.emptyList();
+ } else {
+ result.lengthDelimited =
+ Collections.unmodifiableList(result.lengthDelimited);
+ }
+ if (result.group == null) {
+ result.group = Collections.emptyList();
+ } else {
+ result.group = Collections.unmodifiableList(result.group);
+ }
+
+ final Field returnMe = result;
+ result = null;
+ return returnMe;
+ }
+
+ /** Discard the field's contents. */
+ public Builder clear() {
+ result = new Field();
+ return this;
+ }
+
+ /**
+ * Merge the values in {@code other} into this field. For each list
+ * of values, {@code other}'s values are append to the ones in this
+ * field.
+ */
+ public Builder mergeFrom(final Field other) {
+ if (!other.varint.isEmpty()) {
+ if (result.varint == null) {
+ result.varint = new ArrayList<Long>();
+ }
+ result.varint.addAll(other.varint);
+ }
+ if (!other.fixed32.isEmpty()) {
+ if (result.fixed32 == null) {
+ result.fixed32 = new ArrayList<Integer>();
+ }
+ result.fixed32.addAll(other.fixed32);
+ }
+ if (!other.fixed64.isEmpty()) {
+ if (result.fixed64 == null) {
+ result.fixed64 = new ArrayList<Long>();
+ }
+ result.fixed64.addAll(other.fixed64);
+ }
+ if (!other.lengthDelimited.isEmpty()) {
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = new ArrayList<ByteString>();
+ }
+ result.lengthDelimited.addAll(other.lengthDelimited);
+ }
+ if (!other.group.isEmpty()) {
+ if (result.group == null) {
+ result.group = new ArrayList<UnknownFieldSet>();
+ }
+ result.group.addAll(other.group);
+ }
+ return this;
+ }
+
+ /** Add a varint value. */
+ public Builder addVarint(final long value) {
+ if (result.varint == null) {
+ result.varint = new ArrayList<Long>();
+ }
+ result.varint.add(value);
+ return this;
+ }
+
+ /** Add a fixed32 value. */
+ public Builder addFixed32(final int value) {
+ if (result.fixed32 == null) {
+ result.fixed32 = new ArrayList<Integer>();
+ }
+ result.fixed32.add(value);
+ return this;
+ }
+
+ /** Add a fixed64 value. */
+ public Builder addFixed64(final long value) {
+ if (result.fixed64 == null) {
+ result.fixed64 = new ArrayList<Long>();
+ }
+ result.fixed64.add(value);
+ return this;
+ }
+
+ /** Add a length-delimited value. */
+ public Builder addLengthDelimited(final ByteString value) {
+ if (result.lengthDelimited == null) {
+ result.lengthDelimited = new ArrayList<ByteString>();
+ }
+ result.lengthDelimited.add(value);
+ return this;
+ }
+
+ /** Add an embedded group. */
+ public Builder addGroup(final UnknownFieldSet value) {
+ if (result.group == null) {
+ result.group = new ArrayList<UnknownFieldSet>();
+ }
+ result.group.add(value);
+ return this;
+ }
+ }
+ }
+
+ /**
+ * Parser to implement MessageLite interface.
+ */
+ public static final class Parser extends AbstractParser<UnknownFieldSet> {
+ @Override
+ public UnknownFieldSet parsePartialFrom(
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ }
+
+ private static final Parser PARSER = new Parser();
+ @Override
+ public final Parser getParserForType() {
+ return PARSER;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
new file mode 100644
index 0000000000..d6226fc70c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -0,0 +1,432 @@
+// 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.util.Arrays;
+
+/**
+ * {@code UnknownFieldSetLite} is used to keep track of fields which were seen
+ * when parsing a protocol message but whose field numbers or types are
+ * unrecognized. This most frequently occurs when new fields are added to a
+ * message type and then messages containing those fields are read by old
+ * software that was compiled before the new types were added.
+ *
+ * <p>For use by generated code only.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public final class UnknownFieldSetLite {
+
+ // Arbitrarily chosen.
+ // TODO(dweis): Tune this number?
+ private static final int MIN_CAPACITY = 8;
+
+ private static final UnknownFieldSetLite DEFAULT_INSTANCE =
+ new UnknownFieldSetLite(0, new int[0], new Object[0], false /* isMutable */);
+
+ /**
+ * Get an empty {@code UnknownFieldSetLite}.
+ *
+ * <p>For use by generated code only.
+ */
+ public static UnknownFieldSetLite getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ /**
+ * Returns a new mutable instance.
+ */
+ static UnknownFieldSetLite newInstance() {
+ return new UnknownFieldSetLite();
+ }
+
+ /**
+ * Returns a mutable {@code UnknownFieldSetLite} that is the composite of {@code first} and
+ * {@code second}.
+ */
+ static UnknownFieldSetLite mutableCopyOf(UnknownFieldSetLite first, UnknownFieldSetLite second) {
+ int count = first.count + second.count;
+ int[] tags = Arrays.copyOf(first.tags, count);
+ System.arraycopy(second.tags, 0, tags, first.count, second.count);
+ Object[] objects = Arrays.copyOf(first.objects, count);
+ System.arraycopy(second.objects, 0, objects, first.count, second.count);
+ return new UnknownFieldSetLite(count, tags, objects, true /* isMutable */);
+ }
+
+ /**
+ * The number of elements in the set.
+ */
+ private int count;
+
+ /**
+ * The tag numbers for the elements in the set.
+ */
+ private int[] tags;
+
+ /**
+ * The boxed values of the elements in the set.
+ */
+ private Object[] objects;
+
+ /**
+ * The lazily computed serialized size of the set.
+ */
+ private int memoizedSerializedSize = -1;
+
+ /**
+ * Indicates that this object is mutable.
+ */
+ private boolean isMutable;
+
+ /**
+ * Constructs a mutable {@code UnknownFieldSetLite}.
+ */
+ private UnknownFieldSetLite() {
+ this(0, new int[MIN_CAPACITY], new Object[MIN_CAPACITY], true /* isMutable */);
+ }
+
+ /**
+ * Constructs the {@code UnknownFieldSetLite}.
+ */
+ private UnknownFieldSetLite(int count, int[] tags, Object[] objects, boolean isMutable) {
+ this.count = count;
+ this.tags = tags;
+ this.objects = objects;
+ this.isMutable = isMutable;
+ }
+
+ /**
+ * Marks this object as immutable.
+ *
+ * <p>Future calls to methods that attempt to modify this object will throw.
+ */
+ public void makeImmutable() {
+ this.isMutable = false;
+ }
+
+ /**
+ * Throws an {@link UnsupportedOperationException} if immutable.
+ */
+ void checkMutable() {
+ if (!isMutable) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Serializes the set and writes it to {@code output}.
+ *
+ * <p>For use by generated code only.
+ */
+ public void writeTo(CodedOutputStream output) throws IOException {
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ output.writeUInt64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ output.writeFixed32(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ output.writeFixed64(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ output.writeBytes(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ ((UnknownFieldSetLite) objects[i]).writeTo(output);
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ break;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ /**
+ * Serializes the set and writes it to {@code output} using {@code MessageSet} wire format.
+ *
+ * <p>For use by generated code only.
+ */
+ public void writeAsMessageSetTo(CodedOutputStream output) throws IOException {
+ for (int i = 0; i < count; i++) {
+ int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
+ output.writeRawMessageSetExtension(fieldNumber, (ByteString) objects[i]);
+ }
+ }
+
+
+ /**
+ * Get the number of bytes required to encode this field, including field number, using {@code
+ * MessageSet} wire format.
+ */
+ public int getSerializedSizeAsMessageSet() {
+ int size = memoizedSerializedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ size = 0;
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ size += CodedOutputStream.computeRawMessageSetExtensionSize(
+ fieldNumber, (ByteString) objects[i]);
+ }
+
+ memoizedSerializedSize = size;
+
+ return size;
+ }
+
+ /**
+ * Get the number of bytes required to encode this set.
+ *
+ * <p>For use by generated code only.
+ */
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) {
+ return size;
+ }
+
+ size = 0;
+ for (int i = 0; i < count; i++) {
+ int tag = tags[i];
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ size += CodedOutputStream.computeUInt64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ size += CodedOutputStream.computeFixed32Size(fieldNumber, (Integer) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ size += CodedOutputStream.computeFixed64Size(fieldNumber, (Long) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ size += CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) objects[i]);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ size += CodedOutputStream.computeTagSize(fieldNumber) * 2
+ + ((UnknownFieldSetLite) objects[i]).getSerializedSize();
+ break;
+ default:
+ throw new IllegalStateException(InvalidProtocolBufferException.invalidWireType());
+ }
+ }
+
+ memoizedSerializedSize = size;
+
+ return size;
+ }
+
+ private static boolean equals(int[] tags1, int[] tags2, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (tags1[i] != tags2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean equals(Object[] objects1, Object[] objects2, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (!objects1[i].equals(objects2[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof UnknownFieldSetLite)) {
+ return false;
+ }
+
+ UnknownFieldSetLite other = (UnknownFieldSetLite) obj;
+ if (count != other.count
+ || !equals(tags, other.tags, count)
+ || !equals(objects, other.objects, count)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = 17;
+
+ hashCode = 31 * hashCode + count;
+ hashCode = 31 * hashCode + Arrays.hashCode(tags);
+ hashCode = 31 * hashCode + Arrays.deepHashCode(objects);
+
+ return hashCode;
+ }
+
+ /**
+ * Prints a String representation of the unknown field set.
+ *
+ * <p>For use by generated code only.
+ *
+ * @param buffer the buffer to write to
+ * @param indent the number of spaces the fields should be indented by
+ */
+ final void printWithIndent(StringBuilder buffer, int indent) {
+ for (int i = 0; i < count; i++) {
+ int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
+ MessageLiteToString.printField(buffer, indent, String.valueOf(fieldNumber), objects[i]);
+ }
+ }
+
+ // Package private for unsafe experimental runtime.
+ void storeField(int tag, Object value) {
+ ensureCapacity();
+
+ tags[count] = tag;
+ objects[count] = value;
+ count++;
+ }
+
+ /**
+ * Ensures that our arrays are long enough to store more metadata.
+ */
+ private void ensureCapacity() {
+ if (count == tags.length) {
+ int increment = count < (MIN_CAPACITY / 2) ? MIN_CAPACITY : count >> 1;
+ int newLength = count + increment;
+
+ tags = Arrays.copyOf(tags, newLength);
+ objects = Arrays.copyOf(objects, newLength);
+ }
+ }
+
+ /**
+ * Parse a single field from {@code input} and merge it into this set.
+ *
+ * <p>For use by generated code only.
+ *
+ * @param tag The field's tag number, which was already parsed.
+ * @return {@code false} if the tag is an end group tag.
+ */
+ boolean mergeFieldFrom(final int tag, final CodedInputStream input) throws IOException {
+ checkMutable();
+ final int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ storeField(tag, input.readInt64());
+ return true;
+ case WireFormat.WIRETYPE_FIXED32:
+ storeField(tag, input.readFixed32());
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ storeField(tag, input.readFixed64());
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ storeField(tag, input.readBytes());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final UnknownFieldSetLite subFieldSet = new UnknownFieldSetLite();
+ subFieldSet.mergeFrom(input);
+ input.checkLastTagWas(
+ WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
+ storeField(tag, subFieldSet);
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ /**
+ * Convenience method for merging a new field containing a single varint
+ * value. This is used in particular when an unknown enum value is
+ * encountered.
+ *
+ * <p>For use by generated code only.
+ */
+ UnknownFieldSetLite mergeVarintField(int fieldNumber, int value) {
+ checkMutable();
+ if (fieldNumber == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_VARINT), (long) value);
+
+ return this;
+ }
+
+ /**
+ * Convenience method for merging a length-delimited field.
+ *
+ * <p>For use by generated code only.
+ */
+ UnknownFieldSetLite mergeLengthDelimitedField(final int fieldNumber, final ByteString value) {
+ checkMutable();
+ if (fieldNumber == 0) {
+ throw new IllegalArgumentException("Zero is not a valid field number.");
+ }
+
+ storeField(WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
+
+ return this;
+ }
+
+ /**
+ * Parse an entire message from {@code input} and merge its fields into
+ * this set.
+ */
+ private UnknownFieldSetLite mergeFrom(final CodedInputStream input) throws IOException {
+ // Ensures initialization in mergeFieldFrom.
+ while (true) {
+ final int tag = input.readTag();
+ if (tag == 0 || !mergeFieldFrom(tag, input)) {
+ break;
+ }
+ }
+ return this;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
new file mode 100644
index 0000000000..30e8791178
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -0,0 +1,210 @@
+// 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.util.AbstractList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.RandomAccess;
+
+/**
+ * An implementation of {@link LazyStringList} that wraps another
+ * {@link LazyStringList} such that it cannot be modified via the wrapper.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringList extends AbstractList<String>
+ implements LazyStringList, RandomAccess {
+
+ private final LazyStringList list;
+
+ public UnmodifiableLazyStringList(LazyStringList list) {
+ this.list = list;
+ }
+
+ @Override
+ public String get(int index) {
+ return list.get(index);
+ }
+
+ @Override
+ public Object getRaw(int index) {
+ return list.getRaw(index);
+ }
+
+ @Override
+ public int size() {
+ return list.size();
+ }
+
+ @Override
+ public ByteString getByteString(int index) {
+ return list.getByteString(index);
+ }
+
+ @Override
+ public void add(ByteString element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(int index, ByteString element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAllByteString(Collection<? extends ByteString> element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] getByteArray(int index) {
+ return list.getByteArray(index);
+ }
+
+ @Override
+ public void add(byte[] element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(int index, byte[] element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAllByteArray(Collection<byte[]> element) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ListIterator<String> listIterator(final int index) {
+ return new ListIterator<String>() {
+ ListIterator<String> iter = list.listIterator(index);
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public String next() {
+ return iter.next();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return iter.hasPrevious();
+ }
+
+ @Override
+ public String previous() {
+ return iter.previous();
+ }
+
+ @Override
+ public int nextIndex() {
+ return iter.nextIndex();
+ }
+
+ @Override
+ public int previousIndex() {
+ return iter.previousIndex();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(String o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String o) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return new Iterator<String>() {
+ Iterator<String> iter = list.iterator();
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public String next() {
+ return iter.next();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ @Override
+ public List<?> getUnderlyingElements() {
+ // The returned value is already unmodifiable.
+ return list.getUnderlyingElements();
+ }
+
+ @Override
+ public void mergeFrom(LazyStringList other) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<byte[]> asByteArrayList() {
+ return Collections.unmodifiableList(list.asByteArrayList());
+ }
+
+ @Override
+ public List<ByteString> asByteStringList() {
+ return Collections.unmodifiableList(list.asByteStringList());
+ }
+
+ @Override
+ public LazyStringList getUnmodifiableView() {
+ return this;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
new file mode 100644
index 0000000000..878c775816
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
@@ -0,0 +1,120 @@
+// 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.nio.ByteBuffer;
+
+/**
+ * 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 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!
+ *
+ * <p>This can have a number of significant side affects that have
+ * spooky-action-at-a-distance-like behavior. In particular, if the bytes value changes out from
+ * under a Protocol Buffer:
+ * <ul>
+ * <li>serialization may throw
+ * <li>serialization may succeed but the wrong bytes may be written out
+ * <li>messages are no longer threadsafe
+ * <li>hashCode may be incorrect
+ * <ul>
+ * <li>can result in a permanent memory leak when used as a key in a long-lived HashMap
+ * <li> the semantics of many programs may be violated if this is the case
+ * </ul>
+ * </ul>
+ * Each of these issues will occur in parts of the code base that are entirely distinct from the
+ * parts of the code base modifying the buffer. In fact, both parts of the code base may be correct
+ * - it is the bridging with the unsafe operations that was in error!
+ */
+@ExperimentalApi
+public final class UnsafeByteOperations {
+ private UnsafeByteOperations() {}
+
+ /**
+ * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer.
+ *
+ * @param buffer the buffer to be wrapped
+ * @return a {@link ByteString} backed by the provided buffer
+ */
+ public static ByteString unsafeWrap(byte[] buffer) {
+ return ByteString.wrap(buffer);
+ }
+
+ /**
+ * An unsafe operation that returns a {@link ByteString} that is backed by a subregion of the
+ * provided buffer.
+ *
+ * @param buffer the buffer to be wrapped
+ * @param offset the offset of the wrapped region
+ * @param length the number of bytes of the wrapped region
+ * @return a {@link ByteString} backed by the provided buffer
+ */
+ public static ByteString unsafeWrap(byte[] buffer, int offset, int length) {
+ return ByteString.wrap(buffer, offset, length);
+ }
+
+ /**
+ * An unsafe operation that returns a {@link ByteString} that is backed by the provided buffer.
+ *
+ * @param buffer the Java NIO buffer to be wrapped
+ * @return a {@link ByteString} backed by the provided buffer
+ */
+ public static ByteString unsafeWrap(ByteBuffer buffer) {
+ return ByteString.wrap(buffer);
+ }
+
+ /**
+ * Writes the given {@link ByteString} to the provided {@link ByteOutput}. Calling this method may
+ * result in multiple operations on the target {@link ByteOutput}
+ * (i.e. for roped {@link ByteString}s).
+ *
+ * <p>This method exposes the internal backing buffer(s) of the {@link ByteString} to the {@link
+ * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
+ * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
+ *
+ * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
+ * so may result in corrupted data, which would be difficult to debug.
+ *
+ * @param bytes the {@link ByteString} to be written
+ * @param output the output to receive the bytes
+ * @throws IOException if an I/O error occurs
+ */
+ public static void unsafeWriteTo(ByteString bytes, ByteOutput output) throws IOException {
+ bytes.writeTo(output);
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
new file mode 100644
index 0000000000..5f7bafd602
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -0,0 +1,295 @@
+// 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.lang.reflect.Field;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import sun.misc.Unsafe;
+
+/** Utility class for working with unsafe operations. */
+// TODO(nathanmittler): Add support for Android Memory/MemoryBlock
+final class UnsafeUtil {
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+ private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
+ supportsUnsafeByteBufferOperations();
+ private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
+ private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+ private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(field(Buffer.class, "address"));
+
+ private UnsafeUtil() {}
+
+ static boolean hasUnsafeArrayOperations() {
+ return HAS_UNSAFE_ARRAY_OPERATIONS;
+ }
+
+ static boolean hasUnsafeByteBufferOperations() {
+ return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
+ }
+
+ static Object allocateInstance(Class<?> clazz) {
+ try {
+ return UNSAFE.allocateInstance(clazz);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ static long objectFieldOffset(Field field) {
+ return UNSAFE.objectFieldOffset(field);
+ }
+
+ static long getArrayBaseOffset() {
+ return ARRAY_BASE_OFFSET;
+ }
+
+ static byte getByte(Object target, long offset) {
+ return UNSAFE.getByte(target, offset);
+ }
+
+ static void putByte(Object target, long offset, byte value) {
+ UNSAFE.putByte(target, offset, value);
+ }
+
+ static int getInt(Object target, long offset) {
+ return UNSAFE.getInt(target, offset);
+ }
+
+ static void putInt(Object target, long offset, int value) {
+ UNSAFE.putInt(target, offset, value);
+ }
+
+ static long getLong(Object target, long offset) {
+ return UNSAFE.getLong(target, offset);
+ }
+
+ static void putLong(Object target, long offset, long value) {
+ UNSAFE.putLong(target, offset, value);
+ }
+
+ static boolean getBoolean(Object target, long offset) {
+ return UNSAFE.getBoolean(target, offset);
+ }
+
+ static void putBoolean(Object target, long offset, boolean value) {
+ UNSAFE.putBoolean(target, offset, value);
+ }
+
+ static float getFloat(Object target, long offset) {
+ return UNSAFE.getFloat(target, offset);
+ }
+
+ static void putFloat(Object target, long offset, float value) {
+ UNSAFE.putFloat(target, offset, value);
+ }
+
+ static double getDouble(Object target, long offset) {
+ return UNSAFE.getDouble(target, offset);
+ }
+
+ static void putDouble(Object target, long offset, double value) {
+ UNSAFE.putDouble(target, offset, value);
+ }
+
+ static Object getObject(Object target, long offset) {
+ return UNSAFE.getObject(target, offset);
+ }
+
+ static void putObject(Object target, long offset, Object value) {
+ UNSAFE.putObject(target, offset, value);
+ }
+
+ static void copyMemory(
+ Object src, long srcOffset, Object target, long targetOffset, long length) {
+ UNSAFE.copyMemory(src, srcOffset, target, targetOffset, length);
+ }
+
+ static byte getByte(long address) {
+ return UNSAFE.getByte(address);
+ }
+
+ static void putByte(long address, byte value) {
+ UNSAFE.putByte(address, value);
+ }
+
+ static int getInt(long address) {
+ return UNSAFE.getInt(address);
+ }
+
+ static void putInt(long address, int value) {
+ UNSAFE.putInt(address, value);
+ }
+
+ static long getLong(long address) {
+ return UNSAFE.getLong(address);
+ }
+
+ static void putLong(long address, long value) {
+ UNSAFE.putLong(address, value);
+ }
+
+ static void copyMemory(long srcAddress, long targetAddress, long length) {
+ UNSAFE.copyMemory(srcAddress, targetAddress, length);
+ }
+
+ static void setMemory(long address, long numBytes, byte value) {
+ UNSAFE.setMemory(address, numBytes, value);
+ }
+
+ /**
+ * Gets the offset of the {@code address} field of the given direct {@link ByteBuffer}.
+ */
+ static long addressOffset(ByteBuffer buffer) {
+ return UNSAFE.getLong(buffer, BUFFER_ADDRESS_OFFSET);
+ }
+
+ /**
+ * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this platform.
+ */
+ private static sun.misc.Unsafe getUnsafe() {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe =
+ AccessController.doPrivileged(
+ new PrivilegedExceptionAction<Unsafe>() {
+ @Override
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+ for (Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ // The sun.misc.Unsafe field does not exist.
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+ // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
+ // for Unsafe.
+ }
+ return unsafe;
+ }
+
+ /** Indicates whether or not unsafe array operations are supported on this platform. */
+ private static boolean supportsUnsafeArrayOperations() {
+ boolean supported = false;
+ if (UNSAFE != null) {
+ try {
+ Class<?> clazz = UNSAFE.getClass();
+ clazz.getMethod("objectFieldOffset", Field.class);
+ clazz.getMethod("allocateInstance", Class.class);
+ clazz.getMethod("arrayBaseOffset", Class.class);
+ clazz.getMethod("getByte", Object.class, long.class);
+ clazz.getMethod("putByte", Object.class, long.class, byte.class);
+ clazz.getMethod("getBoolean", Object.class, long.class);
+ clazz.getMethod("putBoolean", Object.class, long.class, boolean.class);
+ clazz.getMethod("getInt", Object.class, long.class);
+ clazz.getMethod("putInt", Object.class, long.class, int.class);
+ clazz.getMethod("getLong", Object.class, long.class);
+ clazz.getMethod("putLong", Object.class, long.class, long.class);
+ clazz.getMethod("getFloat", Object.class, long.class);
+ clazz.getMethod("putFloat", Object.class, long.class, float.class);
+ clazz.getMethod("getDouble", Object.class, long.class);
+ clazz.getMethod("putDouble", Object.class, long.class, double.class);
+ clazz.getMethod("getObject", Object.class, long.class);
+ clazz.getMethod("putObject", Object.class, long.class, Object.class);
+ clazz.getMethod(
+ "copyMemory", Object.class, long.class, Object.class, long.class, long.class);
+ supported = true;
+ } catch (Throwable e) {
+ // Do nothing.
+ }
+ }
+ return supported;
+ }
+
+ private static boolean supportsUnsafeByteBufferOperations() {
+ boolean supported = false;
+ if (UNSAFE != null) {
+ try {
+ Class<?> clazz = UNSAFE.getClass();
+ // Methods for getting direct buffer address.
+ clazz.getMethod("objectFieldOffset", Field.class);
+ clazz.getMethod("getLong", Object.class, long.class);
+
+ clazz.getMethod("getByte", long.class);
+ clazz.getMethod("putByte", long.class, byte.class);
+ clazz.getMethod("getInt", long.class);
+ clazz.getMethod("putInt", long.class, int.class);
+ clazz.getMethod("getLong", long.class);
+ clazz.getMethod("putLong", long.class, long.class);
+ clazz.getMethod("setMemory", long.class, long.class, byte.class);
+ clazz.getMethod("copyMemory", long.class, long.class, long.class);
+ supported = true;
+ } catch (Throwable e) {
+ // Do nothing.
+ }
+ }
+ return supported;
+ }
+
+ /**
+ * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not available.
+ */
+ private static int byteArrayBaseOffset() {
+ return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
+ }
+
+ /**
+ * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
+ * available.
+ */
+ private static long fieldOffset(Field field) {
+ return field == null || UNSAFE == null ? -1 : UNSAFE.objectFieldOffset(field);
+ }
+
+ /**
+ * Gets the field with the given name within the class, or {@code null} if not found. If found,
+ * the field is made accessible.
+ */
+ private static Field field(Class<?> clazz, String fieldName) {
+ Field field;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ } catch (Throwable t) {
+ // Failed to access the fields.
+ field = null;
+ }
+ return field;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
new file mode 100644
index 0000000000..5b80d405eb
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -0,0 +1,1573 @@
+// 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 static com.google.protobuf.UnsafeUtil.addressOffset;
+import static com.google.protobuf.UnsafeUtil.getArrayBaseOffset;
+import static com.google.protobuf.UnsafeUtil.hasUnsafeArrayOperations;
+import static com.google.protobuf.UnsafeUtil.hasUnsafeByteBufferOperations;
+import static java.lang.Character.MAX_SURROGATE;
+import static java.lang.Character.MIN_SURROGATE;
+import static java.lang.Character.isSurrogatePair;
+import static java.lang.Character.toCodePoint;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A set of low-level, high-performance static utility methods related
+ * to the UTF-8 character encoding. This class has no dependencies
+ * outside of the core JDK libraries.
+ *
+ * <p>There are several variants of UTF-8. The one implemented by
+ * this class is the restricted definition of UTF-8 introduced in
+ * Unicode 3.1, which mandates the rejection of "overlong" byte
+ * sequences as well as rejection of 3-byte surrogate codepoint byte
+ * sequences. Note that the UTF-8 decoder included in Oracle's JDK
+ * has been modified to also reject "overlong" byte sequences, but (as
+ * of 2011) still accepts 3-byte surrogate codepoint byte sequences.
+ *
+ * <p>The byte sequences considered valid by this class are exactly
+ * those that can be roundtrip converted to Strings and back to bytes
+ * using the UTF-8 charset, without loss: <pre> {@code
+ * Arrays.equals(bytes, new String(bytes, Internal.UTF_8).getBytes(Internal.UTF_8))
+ * }</pre>
+ *
+ * <p>See the Unicode Standard,</br>
+ * Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
+ * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
+ *
+ * <p>This class supports decoding of partial byte sequences, so that the
+ * bytes in a complete UTF-8 byte sequences can be stored in multiple
+ * segments. Methods typically return {@link #MALFORMED} if the partial
+ * byte sequence is definitely not well-formed, {@link #COMPLETE} if it is
+ * well-formed in the absence of additional input, or if the byte sequence
+ * apparently terminated in the middle of a character, an opaque integer
+ * "state" value containing enough information to decode the character when
+ * passed to a subsequent invocation of a partial decoding method.
+ *
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+// TODO(nathanmittler): Copy changes in this class back to Guava
+final class Utf8 {
+
+ /**
+ * UTF-8 is a runtime hot spot so we attempt to provide heavily optimized implementations
+ * depending on what is available on the platform. The processor is the platform-optimized
+ * delegate for which all methods are delegated directly to.
+ */
+ private static final Processor processor =
+ UnsafeProcessor.isAvailable() ? new UnsafeProcessor() : new SafeProcessor();
+
+ /**
+ * A mask used when performing unsafe reads to determine if a long value contains any non-ASCII
+ * characters (i.e. any byte >= 0x80).
+ */
+ private static final long ASCII_MASK_LONG = 0x8080808080808080L;
+
+ /**
+ * Maximum number of bytes per Java UTF-16 char in UTF-8.
+ * @see java.nio.charset.CharsetEncoder#maxBytesPerChar()
+ */
+ static final int MAX_BYTES_PER_CHAR = 3;
+
+ /**
+ * State value indicating that the byte sequence is well-formed and
+ * complete (no further bytes are needed to complete a character).
+ */
+ public static final int COMPLETE = 0;
+
+ /**
+ * State value indicating that the byte sequence is definitely not
+ * well-formed.
+ */
+ public static final int MALFORMED = -1;
+
+ /**
+ * Used by {@code Unsafe} UTF-8 string validation logic to determine the minimum string length
+ * above which to employ an optimized algorithm for counting ASCII characters. The reason for this
+ * threshold is that for small strings, the optimization may not be beneficial or may even
+ * negatively impact performance since it requires additional logic to avoid unaligned reads
+ * (when calling {@code Unsafe.getLong}). This threshold guarantees that even if the initial
+ * offset is unaligned, we're guaranteed to make at least one call to {@code Unsafe.getLong()}
+ * which provides a performance improvement that entirely subsumes the cost of the additional
+ * logic.
+ */
+ private static final int UNSAFE_COUNT_ASCII_THRESHOLD = 16;
+
+ // Other state values include the partial bytes of the incomplete
+ // character to be decoded in the simplest way: we pack the bytes
+ // into the state int in little-endian order. For example:
+ //
+ // int state = byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+ //
+ // Such a state is unpacked thus (note the ~ operation for byte2 to
+ // undo byte1's sign-extension bits):
+ //
+ // int byte1 = (byte) state;
+ // int byte2 = (byte) ~(state >> 8);
+ // int byte3 = (byte) (state >> 16);
+ //
+ // We cannot store a zero byte in the state because it would be
+ // indistinguishable from the absence of a byte. But we don't need
+ // to, because partial bytes must always be negative. When building
+ // a state, we ensure that byte1 is negative and subsequent bytes
+ // are valid trailing bytes.
+
+ /**
+ * Returns {@code true} if the given byte array is a well-formed
+ * UTF-8 byte sequence.
+ *
+ * <p>This is a convenience method, equivalent to a call to {@code
+ * isValidUtf8(bytes, 0, bytes.length)}.
+ */
+ public static boolean isValidUtf8(byte[] bytes) {
+ return processor.isValidUtf8(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Returns {@code true} if the given byte array slice is a
+ * well-formed UTF-8 byte sequence. The range of bytes to be
+ * checked extends from index {@code index}, inclusive, to {@code
+ * limit}, exclusive.
+ *
+ * <p>This is a convenience method, equivalent to {@code
+ * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+ */
+ public static boolean isValidUtf8(byte[] bytes, int index, int limit) {
+ return processor.isValidUtf8(bytes, index, limit);
+ }
+
+ /**
+ * Tells whether the given byte array slice is a well-formed,
+ * malformed, or incomplete UTF-8 byte sequence. The range of bytes
+ * to be checked extends from index {@code index}, inclusive, to
+ * {@code limit}, exclusive.
+ *
+ * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+ * operation) or the value returned from a call to a partial decoding method
+ * for the previous bytes
+ *
+ * @return {@link #MALFORMED} if the partial byte sequence is
+ * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+ * (no additional input needed), or if the byte sequence is
+ * "incomplete", i.e. apparently terminated in the middle of a character,
+ * an opaque integer "state" value containing enough information to
+ * decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ public static int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) {
+ return processor.partialIsValidUtf8(state, bytes, index, limit);
+ }
+
+ private static int incompleteStateFor(int byte1) {
+ return (byte1 > (byte) 0xF4) ?
+ MALFORMED : byte1;
+ }
+
+ private static int incompleteStateFor(int byte1, int byte2) {
+ return (byte1 > (byte) 0xF4 ||
+ byte2 > (byte) 0xBF) ?
+ MALFORMED : byte1 ^ (byte2 << 8);
+ }
+
+ private static int incompleteStateFor(int byte1, int byte2, int byte3) {
+ return (byte1 > (byte) 0xF4 ||
+ byte2 > (byte) 0xBF ||
+ byte3 > (byte) 0xBF) ?
+ MALFORMED : byte1 ^ (byte2 << 8) ^ (byte3 << 16);
+ }
+
+ private static int incompleteStateFor(byte[] bytes, int index, int limit) {
+ int byte1 = bytes[index - 1];
+ switch (limit - index) {
+ case 0: return incompleteStateFor(byte1);
+ case 1: return incompleteStateFor(byte1, bytes[index]);
+ case 2: return incompleteStateFor(byte1, bytes[index], bytes[index + 1]);
+ default: throw new AssertionError();
+ }
+ }
+
+ private static int incompleteStateFor(
+ final ByteBuffer buffer, final int byte1, final int index, final int remaining) {
+ switch (remaining) {
+ case 0:
+ return incompleteStateFor(byte1);
+ case 1:
+ return incompleteStateFor(byte1, buffer.get(index));
+ case 2:
+ return incompleteStateFor(byte1, buffer.get(index), buffer.get(index + 1));
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ // These UTF-8 handling methods are copied from Guava's Utf8 class with a modification to throw
+ // a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
+ // fallback to more lenient behavior.
+
+ static class UnpairedSurrogateException extends IllegalArgumentException {
+ UnpairedSurrogateException(int index, int length) {
+ super("Unpaired surrogate at index " + index + " of " + length);
+ }
+ }
+
+ /**
+ * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+ * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+ * both time and space.
+ *
+ * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ */
+ static int encodedLength(CharSequence sequence) {
+ // Warning to maintainers: this implementation is highly optimized.
+ int utf16Length = sequence.length();
+ int utf8Length = utf16Length;
+ int i = 0;
+
+ // This loop optimizes for pure ASCII.
+ while (i < utf16Length && sequence.charAt(i) < 0x80) {
+ i++;
+ }
+
+ // This loop optimizes for chars less than 0x800.
+ for (; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += ((0x7f - c) >>> 31); // branch free!
+ } else {
+ utf8Length += encodedLengthGeneral(sequence, i);
+ break;
+ }
+ }
+
+ if (utf8Length < utf16Length) {
+ // Necessary and sufficient condition for overflow because of maximum 3x expansion
+ throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+ + (utf8Length + (1L << 32)));
+ }
+ return utf8Length;
+ }
+
+ private static int encodedLengthGeneral(CharSequence sequence, int start) {
+ int utf16Length = sequence.length();
+ int utf8Length = 0;
+ for (int i = start; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += (0x7f - c) >>> 31; // branch free!
+ } else {
+ utf8Length += 2;
+ // jdk7+: if (Character.isSurrogate(c)) {
+ if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+ // Check that we have a well-formed surrogate pair.
+ int cp = Character.codePointAt(sequence, i);
+ if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ throw new UnpairedSurrogateException(i, utf16Length);
+ }
+ i++;
+ }
+ }
+ }
+ return utf8Length;
+ }
+
+ static int encode(CharSequence in, byte[] out, int offset, int length) {
+ return processor.encodeUtf8(in, out, offset, length);
+ }
+ // End Guava UTF-8 methods.
+
+ /**
+ * Determines if the given {@link ByteBuffer} is a valid UTF-8 string.
+ *
+ * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+ * and the capabilities of the platform.
+ *
+ * @param buffer the buffer to check.
+ * @see Utf8#isValidUtf8(byte[], int, int)
+ */
+ static boolean isValidUtf8(ByteBuffer buffer) {
+ return processor.isValidUtf8(buffer, buffer.position(), buffer.remaining());
+ }
+
+ /**
+ * Determines if the given {@link ByteBuffer} is a partially valid UTF-8 string.
+ *
+ * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+ * and the capabilities of the platform.
+ *
+ * @param buffer the buffer to check.
+ * @see Utf8#partialIsValidUtf8(int, byte[], int, int)
+ */
+ static int partialIsValidUtf8(int state, ByteBuffer buffer, int index, int limit) {
+ return processor.partialIsValidUtf8(state, buffer, index, limit);
+ }
+
+ /**
+ * Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
+ *
+ * <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
+ * and the capabilities of the platform.
+ *
+ * @param in the source string to be encoded
+ * @param out the target buffer to receive the encoded string.
+ * @see Utf8#encode(CharSequence, byte[], int, int)
+ */
+ static void encodeUtf8(CharSequence in, ByteBuffer out) {
+ processor.encodeUtf8(in, out);
+ }
+
+ /**
+ * Counts (approximately) the number of consecutive ASCII characters in the given buffer.
+ * The byte order of the {@link ByteBuffer} does not matter, so performance can be improved if
+ * native byte order is used (i.e. no byte-swapping in {@link ByteBuffer#getLong(int)}).
+ *
+ * @param buffer the buffer to be scanned for ASCII chars
+ * @param index the starting index of the scan
+ * @param limit the limit within buffer for the scan
+ * @return the number of ASCII characters found. The stopping position will be at or
+ * before the first non-ASCII byte.
+ */
+ private static int estimateConsecutiveAscii(ByteBuffer buffer, int index, int limit) {
+ int i = index;
+ final int lim = limit - 7;
+ // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+ // To speed things up further, we're reading longs instead of bytes so we use a mask to
+ // determine if any byte in the current long is non-ASCII.
+ for (; i < lim && (buffer.getLong(i) & ASCII_MASK_LONG) == 0; i += 8) {}
+ return i - index;
+ }
+
+ /**
+ * A processor of UTF-8 strings, providing methods for checking validity and encoding.
+ */
+ // TODO(nathanmittler): Add support for Memory/MemoryBlock on Android.
+ abstract static class Processor {
+ /**
+ * Returns {@code true} if the given byte array slice is a
+ * well-formed UTF-8 byte sequence. The range of bytes to be
+ * checked extends from index {@code index}, inclusive, to {@code
+ * limit}, exclusive.
+ *
+ * <p>This is a convenience method, equivalent to {@code
+ * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+ */
+ final boolean isValidUtf8(byte[] bytes, int index, int limit) {
+ return partialIsValidUtf8(COMPLETE, bytes, index, limit) == COMPLETE;
+ }
+
+ /**
+ * Tells whether the given byte array slice is a well-formed,
+ * malformed, or incomplete UTF-8 byte sequence. The range of bytes
+ * to be checked extends from index {@code index}, inclusive, to
+ * {@code limit}, exclusive.
+ *
+ * @param state either {@link Utf8#COMPLETE} (if this is the initial decoding
+ * operation) or the value returned from a call to a partial decoding method
+ * for the previous bytes
+ *
+ * @return {@link #MALFORMED} if the partial byte sequence is
+ * definitely not well-formed, {@link #COMPLETE} if it is well-formed
+ * (no additional input needed), or if the byte sequence is
+ * "incomplete", i.e. apparently terminated in the middle of a character,
+ * an opaque integer "state" value containing enough information to
+ * decode the character when passed to a subsequent invocation of a
+ * partial decoding method.
+ */
+ abstract int partialIsValidUtf8(int state, byte[] bytes, int index, int limit);
+
+ /**
+ * Returns {@code true} if the given portion of the {@link ByteBuffer} is a
+ * well-formed UTF-8 byte sequence. The range of bytes to be
+ * checked extends from index {@code index}, inclusive, to {@code
+ * limit}, exclusive.
+ *
+ * <p>This is a convenience method, equivalent to {@code
+ * partialIsValidUtf8(bytes, index, limit) == Utf8.COMPLETE}.
+ */
+ final boolean isValidUtf8(ByteBuffer buffer, int index, int limit) {
+ return partialIsValidUtf8(COMPLETE, buffer, index, limit) == COMPLETE;
+ }
+
+ /**
+ * Indicates whether or not the given buffer contains a valid UTF-8 string.
+ *
+ * @param buffer the buffer to check.
+ * @return {@code true} if the given buffer contains a valid UTF-8 string.
+ */
+ final int partialIsValidUtf8(
+ final int state, final ByteBuffer buffer, int index, final int limit) {
+ if (buffer.hasArray()) {
+ final int offset = buffer.arrayOffset();
+ return partialIsValidUtf8(state, buffer.array(), offset + index, offset + limit);
+ } else if (buffer.isDirect()){
+ return partialIsValidUtf8Direct(state, buffer, index, limit);
+ }
+ return partialIsValidUtf8Default(state, buffer, index, limit);
+ }
+
+ /**
+ * Performs validation for direct {@link ByteBuffer} instances.
+ */
+ abstract int partialIsValidUtf8Direct(
+ final int state, final ByteBuffer buffer, int index, final int limit);
+
+ /**
+ * Performs validation for {@link ByteBuffer} instances using the {@link ByteBuffer} API rather
+ * than potentially faster approaches. This first completes validation for the current
+ * character (provided by {@code state}) and then finishes validation for the sequence.
+ */
+ final int partialIsValidUtf8Default(
+ final int state, final ByteBuffer buffer, int index, final int limit) {
+ if (state != COMPLETE) {
+ // The previous decoding operation was incomplete (or malformed).
+ // We look for a well-formed sequence consisting of bytes from
+ // the previous decoding operation (stored in state) together
+ // with bytes from the array slice.
+ //
+ // We expect such "straddler characters" to be rare.
+
+ if (index >= limit) { // No bytes? No progress.
+ return state;
+ }
+
+ byte byte1 = (byte) state;
+ // byte1 is never ASCII.
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ // byte2 trailing-byte test
+ || buffer.get(index++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ // Get byte2 from saved state or array
+ byte byte2 = (byte) ~(state >> 8);
+ if (byte2 == 0) {
+ byte2 = buffer.get(index++);
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ }
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // illegal surrogate codepoint?
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || buffer.get(index++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ // Get byte2 and byte3 from saved state or array
+ byte byte2 = (byte) ~(state >> 8);
+ byte byte3 = 0;
+ if (byte2 == 0) {
+ byte2 = buffer.get(index++);
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ } else {
+ byte3 = (byte) (state >> 16);
+ }
+ if (byte3 == 0) {
+ byte3 = buffer.get(index++);
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2, byte3);
+ }
+ }
+
+ // If we were called with state == MALFORMED, then byte1 is 0xFF,
+ // which never occurs in well-formed UTF-8, and so we will return
+ // MALFORMED again below.
+
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || byte3 > (byte) 0xBF
+ // byte4 trailing-byte test
+ || buffer.get(index++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+
+ // Finish validation for the sequence.
+ return partialIsValidUtf8(buffer, index, limit);
+ }
+
+ /**
+ * Performs validation for {@link ByteBuffer} instances using the {@link ByteBuffer} API rather
+ * than potentially faster approaches.
+ */
+ private static int partialIsValidUtf8(final ByteBuffer buffer, int index, final int limit) {
+ index += estimateConsecutiveAscii(buffer, index, limit);
+
+ for (;;) {
+ // Optimize for interior runs of ASCII bytes.
+ // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+ // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+ int byte1;
+ do {
+ if (index >= limit) {
+ return COMPLETE;
+ }
+ } while ((byte1 = buffer.get(index++)) >= 0);
+
+ // If we're here byte1 is not ASCII. Only need to handle 2-4 byte forms.
+ if (byte1 < (byte) 0xE0) {
+ // Two-byte form (110xxxxx 10xxxxxx)
+ if (index >= limit) {
+ // Incomplete sequence
+ return byte1;
+ }
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2 || buffer.get(index) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ index++;
+ } else if (byte1 < (byte) 0xF0) {
+ // Three-byte form (1110xxxx 10xxxxxx 10xxxxxx)
+ if (index >= limit - 1) {
+ // Incomplete sequence
+ return incompleteStateFor(buffer, byte1, index, limit - index);
+ }
+
+ final byte byte2 = buffer.get(index++);
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // check for illegal surrogate codepoints
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || buffer.get(index) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ index++;
+ } else {
+ // Four-byte form (1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+ if (index >= limit - 2) {
+ // Incomplete sequence
+ return incompleteStateFor(buffer, byte1, index, limit - index);
+ }
+
+ // TODO(nathanmittler): Consider using getInt() to improve performance.
+ final int byte2 = buffer.get(index++);
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || buffer.get(index++) > (byte) 0xBF
+ // byte4 trailing-byte test
+ || buffer.get(index++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+ }
+
+ /**
+ * Encodes an input character sequence ({@code in}) to UTF-8 in the target array ({@code out}).
+ * For a string, this method is similar to
+ * <pre>{@code
+ * byte[] a = string.getBytes(UTF_8);
+ * System.arraycopy(a, 0, bytes, offset, a.length);
+ * return offset + a.length;
+ * }</pre>
+ *
+ * but is more efficient in both time and space. One key difference is that this method
+ * requires paired surrogates, and therefore does not support chunking.
+ * While {@code String.getBytes(UTF_8)} replaces unpaired surrogates with the default
+ * replacement character, this method throws {@link UnpairedSurrogateException}.
+ *
+ * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+ * compute the exact amount needed, or leave room for
+ * {@code Utf8.MAX_BYTES_PER_CHAR * sequence.length()}, which is the largest possible number
+ * of bytes that any input can be encoded to.
+ *
+ * @param in the input character sequence to be encoded
+ * @param out the target array
+ * @param offset the starting offset in {@code bytes} to start writing at
+ * @param length the length of the {@code bytes}, starting from {@code offset}
+ * @throws UnpairedSurrogateException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ * @throws ArrayIndexOutOfBoundsException if {@code sequence} encoded in UTF-8 is longer than
+ * {@code bytes.length - offset}
+ * @return the new offset, equivalent to {@code offset + Utf8.encodedLength(sequence)}
+ */
+ abstract int encodeUtf8(CharSequence in, byte[] out, int offset, int length);
+
+ /**
+ * Encodes an input character sequence ({@code in}) to UTF-8 in the target buffer ({@code out}).
+ * Upon returning from this method, the {@code out} position will point to the position after
+ * the last encoded byte. This method requires paired surrogates, and therefore does not
+ * support chunking.
+ *
+ * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+ * compute the exact amount needed, or leave room for
+ * {@code Utf8.MAX_BYTES_PER_CHAR * in.length()}, which is the largest possible number
+ * of bytes that any input can be encoded to.
+ *
+ * @param in the source character sequence to be encoded
+ * @param out the target buffer
+ * @throws UnpairedSurrogateException if {@code in} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ * @throws ArrayIndexOutOfBoundsException if {@code in} encoded in UTF-8 is longer than
+ * {@code out.remaining()}
+ */
+ final void encodeUtf8(CharSequence in, ByteBuffer out) {
+ if (out.hasArray()) {
+ final int offset = out.arrayOffset();
+ int endIndex =
+ Utf8.encode(in, out.array(), offset + out.position(), out.remaining());
+ out.position(endIndex - offset);
+ } else if (out.isDirect()) {
+ encodeUtf8Direct(in, out);
+ } else {
+ encodeUtf8Default(in, out);
+ }
+ }
+
+ /**
+ * Encodes the input character sequence to a direct {@link ByteBuffer} instance.
+ */
+ abstract void encodeUtf8Direct(CharSequence in, ByteBuffer out);
+
+ /**
+ * Encodes the input character sequence to a {@link ByteBuffer} instance using the {@link
+ * ByteBuffer} API, rather than potentially faster approaches.
+ */
+ final void encodeUtf8Default(CharSequence in, ByteBuffer out) {
+ final int inLength = in.length();
+ int outIx = out.position();
+ int inIx = 0;
+
+ // Since ByteBuffer.putXXX() already checks boundaries for us, no need to explicitly check
+ // access. Assume the buffer is big enough and let it handle the out of bounds exception
+ // if it occurs.
+ try {
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; inIx < inLength && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+ out.put(outIx + inIx, (byte) c);
+ }
+ if (inIx == inLength) {
+ // Successfully encoded the entire string.
+ out.position(outIx + inIx);
+ return;
+ }
+
+ outIx += inIx;
+ for (char c; inIx < inLength; ++inIx, ++outIx) {
+ c = in.charAt(inIx);
+ if (c < 0x80) {
+ // One byte (0xxx xxxx)
+ out.put(outIx, (byte) c);
+ } else if (c < 0x800) {
+ // Two bytes (110x xxxx 10xx xxxx)
+
+ // Benchmarks show put performs better than putShort here (for HotSpot).
+ out.put(outIx++, (byte) (0xC0 | (c >>> 6)));
+ out.put(outIx, (byte) (0x80 | (0x3F & c)));
+ } else if (c < MIN_SURROGATE || MAX_SURROGATE < c) {
+ // Three bytes (1110 xxxx 10xx xxxx 10xx xxxx)
+ // Maximum single-char code point is 0xFFFF, 16 bits.
+
+ // Benchmarks show put performs better than putShort here (for HotSpot).
+ out.put(outIx++, (byte) (0xE0 | (c >>> 12)));
+ out.put(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+ out.put(outIx, (byte) (0x80 | (0x3F & c)));
+ } else {
+ // Four bytes (1111 xxxx 10xx xxxx 10xx xxxx 10xx xxxx)
+
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+ // bytes
+ final char low;
+ if (inIx + 1 == inLength || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+ throw new UnpairedSurrogateException(inIx, inLength);
+ }
+ // TODO(nathanmittler): Consider using putInt() to improve performance.
+ int codePoint = toCodePoint(c, low);
+ out.put(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ out.put(outIx, (byte) (0x80 | (0x3F & codePoint)));
+ }
+ }
+
+ // Successfully encoded the entire string.
+ out.position(outIx);
+ } catch (IndexOutOfBoundsException e) {
+ // TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead.
+
+ // If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
+ // use inIx to determine the bad write index.
+ int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
+ throw new ArrayIndexOutOfBoundsException(
+ "Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
+ }
+ }
+ }
+
+ /**
+ * {@link Processor} implementation that does not use any {@code sun.misc.Unsafe} methods.
+ */
+ static final class SafeProcessor extends Processor {
+ @Override
+ int partialIsValidUtf8(int state, byte[] bytes, int index, int limit) {
+ if (state != COMPLETE) {
+ // The previous decoding operation was incomplete (or malformed).
+ // We look for a well-formed sequence consisting of bytes from
+ // the previous decoding operation (stored in state) together
+ // with bytes from the array slice.
+ //
+ // We expect such "straddler characters" to be rare.
+
+ if (index >= limit) { // No bytes? No progress.
+ return state;
+ }
+ int byte1 = (byte) state;
+ // byte1 is never ASCII.
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ // byte2 trailing-byte test
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ // Get byte2 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ if (byte2 == 0) {
+ byte2 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ }
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // illegal surrogate codepoint?
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ // Get byte2 and byte3 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ int byte3 = 0;
+ if (byte2 == 0) {
+ byte2 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ } else {
+ byte3 = (byte) (state >> 16);
+ }
+ if (byte3 == 0) {
+ byte3 = bytes[index++];
+ if (index >= limit) {
+ return incompleteStateFor(byte1, byte2, byte3);
+ }
+ }
+
+ // If we were called with state == MALFORMED, then byte1 is 0xFF,
+ // which never occurs in well-formed UTF-8, and so we will return
+ // MALFORMED again below.
+
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || byte3 > (byte) 0xBF
+ // byte4 trailing-byte test
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+
+ return partialIsValidUtf8(bytes, index, limit);
+ }
+
+ @Override
+ int partialIsValidUtf8Direct(int state, ByteBuffer buffer, int index, int limit) {
+ // For safe processing, we have to use the ByteBuffer API.
+ return partialIsValidUtf8Default(state, buffer, index, limit);
+ }
+
+ @Override
+ int encodeUtf8(CharSequence in, byte[] out, int offset, int length) {
+ int utf16Length = in.length();
+ int j = offset;
+ int i = 0;
+ int limit = offset + length;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i < utf16Length && i + j < limit && (c = in.charAt(i)) < 0x80; i++) {
+ out[j + i] = (byte) c;
+ }
+ if (i == utf16Length) {
+ return j + utf16Length;
+ }
+ j += i;
+ for (char c; i < utf16Length; i++) {
+ c = in.charAt(i);
+ if (c < 0x80 && j < limit) {
+ out[j++] = (byte) c;
+ } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+ out[j++] = (byte) ((0xF << 6) | (c >>> 6));
+ out[j++] = (byte) (0x80 | (0x3F & c));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ out[j++] = (byte) ((0xF << 5) | (c >>> 12));
+ out[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+ out[j++] = (byte) (0x80 | (0x3F & c));
+ } else if (j <= limit - 4) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+ // four UTF-8 bytes
+ final char low;
+ if (i + 1 == in.length()
+ || !Character.isSurrogatePair(c, (low = in.charAt(++i)))) {
+ throw new UnpairedSurrogateException((i - 1), utf16Length);
+ }
+ int codePoint = Character.toCodePoint(c, low);
+ out[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+ out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+ out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+ out[j++] = (byte) (0x80 | (0x3F & codePoint));
+ } else {
+ // If we are surrogates and we're not a surrogate pair, always throw an
+ // UnpairedSurrogateException instead of an ArrayOutOfBoundsException.
+ if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
+ && (i + 1 == in.length()
+ || !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
+ throw new UnpairedSurrogateException(i, utf16Length);
+ }
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+ }
+ }
+ return j;
+ }
+
+ @Override
+ void encodeUtf8Direct(CharSequence in, ByteBuffer out) {
+ // For safe processing, we have to use the ByteBuffer API.
+ encodeUtf8Default(in, out);
+ }
+
+ private static int partialIsValidUtf8(byte[] bytes, int index, int limit) {
+ // Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
+ // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+ while (index < limit && bytes[index] >= 0) {
+ index++;
+ }
+
+ return (index >= limit) ? COMPLETE : partialIsValidUtf8NonAscii(bytes, index, limit);
+ }
+
+ private static int partialIsValidUtf8NonAscii(byte[] bytes, int index, int limit) {
+ for (;;) {
+ int byte1, byte2;
+
+ // Optimize for interior runs of ASCII bytes.
+ do {
+ if (index >= limit) {
+ return COMPLETE;
+ }
+ } while ((byte1 = bytes[index++]) >= 0);
+
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ if (index >= limit) {
+ // Incomplete sequence
+ return byte1;
+ }
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ if (index >= limit - 1) { // incomplete sequence
+ return incompleteStateFor(bytes, index, limit);
+ }
+ if ((byte2 = bytes[index++]) > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // check for illegal surrogate codepoints
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ if (index >= limit - 2) { // incomplete sequence
+ return incompleteStateFor(bytes, index, limit);
+ }
+ if ((byte2 = bytes[index++]) > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || bytes[index++] > (byte) 0xBF
+ // byte4 trailing-byte test
+ || bytes[index++] > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * {@link Processor} that uses {@code sun.misc.Unsafe} where possible to improve performance.
+ */
+ static final class UnsafeProcessor extends Processor {
+ /**
+ * Indicates whether or not all required unsafe operations are supported on this platform.
+ */
+ static boolean isAvailable() {
+ return hasUnsafeArrayOperations() && hasUnsafeByteBufferOperations();
+ }
+
+ @Override
+ int partialIsValidUtf8(int state, byte[] bytes, final int index, final int limit) {
+ if ((index | limit | bytes.length - limit) < 0) {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
+ }
+ long offset = getArrayBaseOffset() + index;
+ final long offsetLimit = getArrayBaseOffset() + limit;
+ if (state != COMPLETE) {
+ // The previous decoding operation was incomplete (or malformed).
+ // We look for a well-formed sequence consisting of bytes from
+ // the previous decoding operation (stored in state) together
+ // with bytes from the array slice.
+ //
+ // We expect such "straddler characters" to be rare.
+
+ if (offset >= offsetLimit) { // No bytes? No progress.
+ return state;
+ }
+ int byte1 = (byte) state;
+ // byte1 is never ASCII.
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ // byte2 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ // Get byte2 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ if (byte2 == 0) {
+ byte2 = UnsafeUtil.getByte(bytes, offset++);
+ if (offset >= offsetLimit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ }
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // illegal surrogate codepoint?
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ // Get byte2 and byte3 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ int byte3 = 0;
+ if (byte2 == 0) {
+ byte2 = UnsafeUtil.getByte(bytes, offset++);
+ if (offset >= offsetLimit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ } else {
+ byte3 = (byte) (state >> 16);
+ }
+ if (byte3 == 0) {
+ byte3 = UnsafeUtil.getByte(bytes, offset++);
+ if (offset >= offsetLimit) {
+ return incompleteStateFor(byte1, byte2, byte3);
+ }
+ }
+
+ // If we were called with state == MALFORMED, then byte1 is 0xFF,
+ // which never occurs in well-formed UTF-8, and so we will return
+ // MALFORMED again below.
+
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || byte3 > (byte) 0xBF
+ // byte4 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+
+ return partialIsValidUtf8(bytes, offset, (int) (offsetLimit - offset));
+ }
+
+ @Override
+ int partialIsValidUtf8Direct(
+ final int state, ByteBuffer buffer, final int index, final int limit) {
+ if ((index | limit | buffer.limit() - limit) < 0) {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(), index, limit));
+ }
+ long address = addressOffset(buffer) + index;
+ final long addressLimit = address + (limit - index);
+ if (state != COMPLETE) {
+ // The previous decoding operation was incomplete (or malformed).
+ // We look for a well-formed sequence consisting of bytes from
+ // the previous decoding operation (stored in state) together
+ // with bytes from the array slice.
+ //
+ // We expect such "straddler characters" to be rare.
+
+ if (address >= addressLimit) { // No bytes? No progress.
+ return state;
+ }
+
+ final int byte1 = (byte) state;
+ // byte1 is never ASCII.
+ if (byte1 < (byte) 0xE0) {
+ // two-byte form
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ // byte2 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // three-byte form
+
+ // Get byte2 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ if (byte2 == 0) {
+ byte2 = UnsafeUtil.getByte(address++);
+ if (address >= addressLimit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ }
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // illegal surrogate codepoint?
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // four-byte form
+
+ // Get byte2 and byte3 from saved state or array
+ int byte2 = (byte) ~(state >> 8);
+ int byte3 = 0;
+ if (byte2 == 0) {
+ byte2 = UnsafeUtil.getByte(address++);
+ if (address >= addressLimit) {
+ return incompleteStateFor(byte1, byte2);
+ }
+ } else {
+ byte3 = (byte) (state >> 16);
+ }
+ if (byte3 == 0) {
+ byte3 = UnsafeUtil.getByte(address++);
+ if (address >= addressLimit) {
+ return incompleteStateFor(byte1, byte2, byte3);
+ }
+ }
+
+ // If we were called with state == MALFORMED, then byte1 is 0xFF,
+ // which never occurs in well-formed UTF-8, and so we will return
+ // MALFORMED again below.
+
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || byte3 > (byte) 0xBF
+ // byte4 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+
+ return partialIsValidUtf8(address, (int) (addressLimit - address));
+ }
+
+ @Override
+ int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
+ long outIx = getArrayBaseOffset() + offset;
+ final long outLimit = outIx + length;
+ final int inLimit = in.length();
+ if (inLimit > length || out.length - length < offset) {
+ // Not even enough room for an ASCII-encoded string.
+ throw new ArrayIndexOutOfBoundsException(
+ "Failed writing " + in.charAt(inLimit - 1) + " at index " + (offset + length));
+ }
+
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ int inIx = 0;
+ for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+ UnsafeUtil.putByte(out, outIx++, (byte) c);
+ }
+ if (inIx == inLimit) {
+ // We're done, it was ASCII encoded.
+ return (int) (outIx - getArrayBaseOffset());
+ }
+
+ for (char c; inIx < inLimit; ++inIx) {
+ c = in.charAt(inIx);
+ if (c < 0x80 && outIx < outLimit) {
+ UnsafeUtil.putByte(out, outIx++, (byte) c);
+ } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
+ UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+ } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & c)));
+ } else if (outIx <= outLimit - 4L) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+ // bytes
+ final char low;
+ if (inIx + 1 == inLimit || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+ throw new UnpairedSurrogateException((inIx - 1), inLimit);
+ }
+ int codePoint = toCodePoint(c, low);
+ UnsafeUtil.putByte(out, outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UnsafeUtil.putByte(out, outIx++, (byte) (0x80 | (0x3F & codePoint)));
+ } else {
+ if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
+ && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
+ // We are surrogates and we're not a surrogate pair.
+ throw new UnpairedSurrogateException(inIx, inLimit);
+ }
+ // Not enough space in the output buffer.
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+ }
+ }
+
+ // All bytes have been encoded.
+ return (int) (outIx - getArrayBaseOffset());
+ }
+
+ @Override
+ void encodeUtf8Direct(CharSequence in, ByteBuffer out) {
+ final long address = addressOffset(out);
+ long outIx = address + out.position();
+ final long outLimit = address + out.limit();
+ final int inLimit = in.length();
+ if (inLimit > outLimit - outIx) {
+ // Not even enough room for an ASCII-encoded string.
+ throw new ArrayIndexOutOfBoundsException(
+ "Failed writing " + in.charAt(inLimit - 1) + " at index " + out.limit());
+ }
+
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ int inIx = 0;
+ for (char c; inIx < inLimit && (c = in.charAt(inIx)) < 0x80; ++inIx) {
+ UnsafeUtil.putByte(outIx++, (byte) c);
+ }
+ if (inIx == inLimit) {
+ // We're done, it was ASCII encoded.
+ out.position((int) (outIx - address));
+ return;
+ }
+
+ for (char c; inIx < inLimit; ++inIx) {
+ c = in.charAt(inIx);
+ if (c < 0x80 && outIx < outLimit) {
+ UnsafeUtil.putByte(outIx++, (byte) c);
+ } else if (c < 0x800 && outIx <= outLimit - 2L) { // 11 bits, two UTF-8 bytes
+ UnsafeUtil.putByte(outIx++, (byte) ((0xF << 6) | (c >>> 6)));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+ } else if ((c < MIN_SURROGATE || MAX_SURROGATE < c) && outIx <= outLimit - 3L) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ UnsafeUtil.putByte(outIx++, (byte) ((0xF << 5) | (c >>> 12)));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & c)));
+ } else if (outIx <= outLimit - 4L) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
+ // bytes
+ final char low;
+ if (inIx + 1 == inLimit || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
+ throw new UnpairedSurrogateException((inIx - 1), inLimit);
+ }
+ int codePoint = toCodePoint(c, low);
+ UnsafeUtil.putByte(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UnsafeUtil.putByte(outIx++, (byte) (0x80 | (0x3F & codePoint)));
+ } else {
+ if ((MIN_SURROGATE <= c && c <= MAX_SURROGATE)
+ && (inIx + 1 == inLimit || !isSurrogatePair(c, in.charAt(inIx + 1)))) {
+ // We are surrogates and we're not a surrogate pair.
+ throw new UnpairedSurrogateException(inIx, inLimit);
+ }
+ // Not enough space in the output buffer.
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + outIx);
+ }
+ }
+
+ // All bytes have been encoded.
+ out.position((int) (outIx - address));
+ }
+
+ /**
+ * Counts (approximately) the number of consecutive ASCII characters starting from the given
+ * position, using the most efficient method available to the platform.
+ *
+ * @param bytes the array containing the character sequence
+ * @param offset the offset position of the index (same as index + arrayBaseOffset)
+ * @param maxChars the maximum number of characters to count
+ * @return the number of ASCII characters found. The stopping position will be at or
+ * before the first non-ASCII byte.
+ */
+ private static int unsafeEstimateConsecutiveAscii(
+ byte[] bytes, long offset, final int maxChars) {
+ int remaining = maxChars;
+ if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
+ // Don't bother with small strings.
+ return 0;
+ }
+
+ // Read bytes until 8-byte aligned so that we can read longs in the loop below.
+ // Byte arrays are already either 8 or 16-byte aligned, so we just need to make sure that
+ // the index (relative to the start of the array) is also 8-byte aligned. We do this by
+ // ANDing the index with 7 to determine the number of bytes that need to be read before
+ // we're 8-byte aligned.
+ final int unaligned = (int) offset & 7;
+ for (int j = unaligned; j > 0; j--) {
+ if (UnsafeUtil.getByte(bytes, offset++) < 0) {
+ return unaligned - j;
+ }
+ }
+
+ // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+ // To speed things up further, we're reading longs instead of bytes so we use a mask to
+ // determine if any byte in the current long is non-ASCII.
+ remaining -= unaligned;
+ for (; remaining >= 8 && (UnsafeUtil.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
+ offset += 8, remaining -= 8) {}
+ return maxChars - remaining;
+ }
+
+ /**
+ * Same as {@link Utf8#estimateConsecutiveAscii(ByteBuffer, int, int)} except that it uses the
+ * most efficient method available to the platform.
+ */
+ private static int unsafeEstimateConsecutiveAscii(long address, final int maxChars) {
+ int remaining = maxChars;
+ if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
+ // Don't bother with small strings.
+ return 0;
+ }
+
+ // Read bytes until 8-byte aligned so that we can read longs in the loop below.
+ // We do this by ANDing the address with 7 to determine the number of bytes that need to
+ // be read before we're 8-byte aligned.
+ final int unaligned = (int) address & 7;
+ for (int j = unaligned; j > 0; j--) {
+ if (UnsafeUtil.getByte(address++) < 0) {
+ return unaligned - j;
+ }
+ }
+
+ // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
+ // To speed things up further, we're reading longs instead of bytes so we use a mask to
+ // determine if any byte in the current long is non-ASCII.
+ remaining -= unaligned;
+ for (; remaining >= 8 && (UnsafeUtil.getLong(address) & ASCII_MASK_LONG) == 0;
+ address += 8, remaining -= 8) {}
+ return maxChars - remaining;
+ }
+
+ private static int partialIsValidUtf8(final byte[] bytes, long offset, int remaining) {
+ // Skip past ASCII characters as quickly as possible.
+ final int skipped = unsafeEstimateConsecutiveAscii(bytes, offset, remaining);
+ remaining -= skipped;
+ offset += skipped;
+
+ for (;;) {
+ // Optimize for interior runs of ASCII bytes.
+ // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+ // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+ int byte1 = 0;
+ for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(bytes, offset++)) >= 0; --remaining) {
+ }
+ if (remaining == 0) {
+ return COMPLETE;
+ }
+ remaining--;
+
+ // If we're here byte1 is not ASCII. Only need to handle 2-4 byte forms.
+ if (byte1 < (byte) 0xE0) {
+ // Two-byte form (110xxxxx 10xxxxxx)
+ if (remaining == 0) {
+ // Incomplete sequence
+ return byte1;
+ }
+ remaining--;
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // Three-byte form (1110xxxx 10xxxxxx 10xxxxxx)
+ if (remaining < 2) {
+ // Incomplete sequence
+ return unsafeIncompleteStateFor(bytes, byte1, offset, remaining);
+ }
+ remaining -= 2;
+
+ final int byte2;
+ if ((byte2 = UnsafeUtil.getByte(bytes, offset++)) > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // check for illegal surrogate codepoints
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // Four-byte form (1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx)
+ if (remaining < 3) {
+ // Incomplete sequence
+ return unsafeIncompleteStateFor(bytes, byte1, offset, remaining);
+ }
+ remaining -= 3;
+
+ final int byte2;
+ if ((byte2 = UnsafeUtil.getByte(bytes, offset++)) > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF
+ // byte4 trailing-byte test
+ || UnsafeUtil.getByte(bytes, offset++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+ }
+
+ private static int partialIsValidUtf8(long address, int remaining) {
+ // Skip past ASCII characters as quickly as possible.
+ final int skipped = unsafeEstimateConsecutiveAscii(address, remaining);
+ address += skipped;
+ remaining -= skipped;
+
+ for (;;) {
+ // Optimize for interior runs of ASCII bytes.
+ // TODO(nathanmittler): Consider checking 8 bytes at a time after some threshold?
+ // Maybe after seeing a few in a row that are ASCII, go back to fast mode?
+ int byte1 = 0;
+ for (; remaining > 0 && (byte1 = UnsafeUtil.getByte(address++)) >= 0; --remaining) {
+ }
+ if (remaining == 0) {
+ return COMPLETE;
+ }
+ remaining--;
+
+ if (byte1 < (byte) 0xE0) {
+ // Two-byte form
+
+ if (remaining == 0) {
+ // Incomplete sequence
+ return byte1;
+ }
+ remaining--;
+
+ // Simultaneously checks for illegal trailing-byte in
+ // leading position and overlong 2-byte form.
+ if (byte1 < (byte) 0xC2 || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else if (byte1 < (byte) 0xF0) {
+ // Three-byte form
+
+ if (remaining < 2) {
+ // Incomplete sequence
+ return unsafeIncompleteStateFor(address, byte1, remaining);
+ }
+ remaining -= 2;
+
+ final byte byte2 = UnsafeUtil.getByte(address++);
+ if (byte2 > (byte) 0xBF
+ // overlong? 5 most significant bits must not all be zero
+ || (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
+ // check for illegal surrogate codepoints
+ || (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ } else {
+ // Four-byte form
+
+ if (remaining < 3) {
+ // Incomplete sequence
+ return unsafeIncompleteStateFor(address, byte1, remaining);
+ }
+ remaining -= 3;
+
+ final byte byte2 = UnsafeUtil.getByte(address++);
+ if (byte2 > (byte) 0xBF
+ // Check that 1 <= plane <= 16. Tricky optimized form of:
+ // if (byte1 > (byte) 0xF4 ||
+ // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
+ // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
+ || (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
+ // byte3 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF
+ // byte4 trailing-byte test
+ || UnsafeUtil.getByte(address++) > (byte) 0xBF) {
+ return MALFORMED;
+ }
+ }
+ }
+ }
+
+ private static int unsafeIncompleteStateFor(byte[] bytes, int byte1, long offset,
+ int remaining) {
+ switch (remaining) {
+ case 0: {
+ return incompleteStateFor(byte1);
+ }
+ case 1: {
+ return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset));
+ }
+ case 2: {
+ return incompleteStateFor(byte1, UnsafeUtil.getByte(bytes, offset),
+ UnsafeUtil.getByte(bytes, offset + 1));
+ }
+ default: {
+ throw new AssertionError();
+ }
+ }
+ }
+
+ private static int unsafeIncompleteStateFor(long address, final int byte1, int remaining) {
+ switch (remaining) {
+ case 0: {
+ return incompleteStateFor(byte1);
+ }
+ case 1: {
+ return incompleteStateFor(byte1, UnsafeUtil.getByte(address));
+ }
+ case 2: {
+ return incompleteStateFor(byte1, UnsafeUtil.getByte(address),
+ UnsafeUtil.getByte(address + 1));
+ }
+ default: {
+ throw new AssertionError();
+ }
+ }
+ }
+ }
+
+ private Utf8() {}
+}
diff --git a/third_party/protobuf/java/core/src/main/java/com/google/protobuf/WireFormat.java b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/WireFormat.java
new file mode 100644
index 0000000000..0b0cdb7d0e
--- /dev/null
+++ b/third_party/protobuf/java/core/src/main/java/com/google/protobuf/WireFormat.java
@@ -0,0 +1,260 @@
+// 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;
+
+/**
+ * This class is used internally by the Protocol Buffer library and generated
+ * message implementations. It is public only because those generated messages
+ * do not reside in the {@code protobuf} package. Others should not use this
+ * class directly.
+ *
+ * This class contains constants and helper functions useful for dealing with
+ * the Protocol Buffer wire format.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class WireFormat {
+ // Do not allow instantiation.
+ private WireFormat() {}
+
+ static final int FIXED_32_SIZE = 4;
+ static final int FIXED_64_SIZE = 8;
+ static final int MAX_VARINT_SIZE = 10;
+
+ public static final int WIRETYPE_VARINT = 0;
+ public static final int WIRETYPE_FIXED64 = 1;
+ public static final int WIRETYPE_LENGTH_DELIMITED = 2;
+ public static final int WIRETYPE_START_GROUP = 3;
+ public static final int WIRETYPE_END_GROUP = 4;
+ public static final int WIRETYPE_FIXED32 = 5;
+
+ static final int TAG_TYPE_BITS = 3;
+ static final int TAG_TYPE_MASK = (1 << TAG_TYPE_BITS) - 1;
+
+ /** Given a tag value, determines the wire type (the lower 3 bits). */
+ public static int getTagWireType(final int tag) {
+ return tag & TAG_TYPE_MASK;
+ }
+
+ /** Given a tag value, determines the field number (the upper 29 bits). */
+ public static int getTagFieldNumber(final int tag) {
+ return tag >>> TAG_TYPE_BITS;
+ }
+
+ /** Makes a tag value given a field number and wire type. */
+ static int makeTag(final int fieldNumber, final int wireType) {
+ return (fieldNumber << TAG_TYPE_BITS) | wireType;
+ }
+
+ /**
+ * Lite equivalent to {@link Descriptors.FieldDescriptor.JavaType}. This is
+ * only here to support the lite runtime and should not be used by users.
+ */
+ public enum JavaType {
+ INT(0),
+ LONG(0L),
+ FLOAT(0F),
+ DOUBLE(0D),
+ BOOLEAN(false),
+ STRING(""),
+ BYTE_STRING(ByteString.EMPTY),
+ ENUM(null),
+ MESSAGE(null);
+
+ JavaType(final Object defaultDefault) {
+ this.defaultDefault = defaultDefault;
+ }
+
+ /**
+ * The default default value for fields of this type, if it's a primitive
+ * type.
+ */
+ Object getDefaultDefault() {
+ return defaultDefault;
+ }
+
+ private final Object defaultDefault;
+ }
+
+ /**
+ * Lite equivalent to {@link Descriptors.FieldDescriptor.Type}. This is
+ * only here to support the lite runtime and should not be used by users.
+ */
+ public enum FieldType {
+ DOUBLE (JavaType.DOUBLE , WIRETYPE_FIXED64 ),
+ FLOAT (JavaType.FLOAT , WIRETYPE_FIXED32 ),
+ INT64 (JavaType.LONG , WIRETYPE_VARINT ),
+ UINT64 (JavaType.LONG , WIRETYPE_VARINT ),
+ INT32 (JavaType.INT , WIRETYPE_VARINT ),
+ FIXED64 (JavaType.LONG , WIRETYPE_FIXED64 ),
+ FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ),
+ BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ),
+ STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) {
+ @Override
+ public boolean isPackable() {
+ return false; }
+ },
+ GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) {
+ @Override
+ public boolean isPackable() {
+ return false; }
+ },
+ MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) {
+ @Override
+ public boolean isPackable() {
+ return false; }
+ },
+ BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
+ @Override
+ public boolean isPackable() {
+ return false; }
+ },
+ UINT32 (JavaType.INT , WIRETYPE_VARINT ),
+ ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
+ SFIXED32(JavaType.INT , WIRETYPE_FIXED32 ),
+ SFIXED64(JavaType.LONG , WIRETYPE_FIXED64 ),
+ SINT32 (JavaType.INT , WIRETYPE_VARINT ),
+ SINT64 (JavaType.LONG , WIRETYPE_VARINT );
+
+ FieldType(final JavaType javaType, final int wireType) {
+ this.javaType = javaType;
+ this.wireType = wireType;
+ }
+
+ private final JavaType javaType;
+ private final int wireType;
+
+ public JavaType getJavaType() { return javaType; }
+ public int getWireType() { return wireType; }
+
+ public boolean isPackable() { return true; }
+ }
+
+ // Field numbers for fields in MessageSet wire format.
+ static final int MESSAGE_SET_ITEM = 1;
+ static final int MESSAGE_SET_TYPE_ID = 2;
+ static final int MESSAGE_SET_MESSAGE = 3;
+
+ // Tag numbers.
+ static final int MESSAGE_SET_ITEM_TAG =
+ makeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
+ static final int MESSAGE_SET_ITEM_END_TAG =
+ makeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
+ static final int MESSAGE_SET_TYPE_ID_TAG =
+ makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT);
+ static final int MESSAGE_SET_MESSAGE_TAG =
+ makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED);
+
+ /**
+ * Validation level for handling incoming string field data which potentially
+ * contain non-UTF8 bytes.
+ */
+ enum Utf8Validation {
+ /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
+ LOOSE {
+ @Override
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readString();
+ }
+ },
+ /** Eagerly parses to String; throws an IOException on invalid bytes. */
+ STRICT {
+ @Override
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readStringRequireUtf8();
+ }
+ },
+ /** Keep data as ByteString; validation/conversion to String is lazy. */
+ LAZY {
+ @Override
+ Object readString(CodedInputStream input) throws IOException {
+ return input.readBytes();
+ }
+ };
+
+ /** Read a string field from the input with the proper UTF8 validation. */
+ abstract Object readString(CodedInputStream input) throws IOException;
+ }
+
+ /**
+ * Read a field of any primitive type for immutable messages from a
+ * CodedInputStream. Enums, groups, and embedded messages are not handled by
+ * this method.
+ *
+ * @param input The stream from which to read.
+ * @param type Declared type of the field.
+ * @param utf8Validation Different string UTF8 validation level for handling
+ * string fields.
+ * @return An object representing the field's value, of the exact
+ * type which would be returned by
+ * {@link Message#getField(Descriptors.FieldDescriptor)} for
+ * this field.
+ */
+ static Object readPrimitiveField(
+ CodedInputStream input,
+ FieldType type,
+ Utf8Validation utf8Validation) throws IOException {
+ switch (type) {
+ case DOUBLE : return input.readDouble ();
+ case FLOAT : return input.readFloat ();
+ case INT64 : return input.readInt64 ();
+ case UINT64 : return input.readUInt64 ();
+ case INT32 : return input.readInt32 ();
+ case FIXED64 : return input.readFixed64 ();
+ case FIXED32 : return input.readFixed32 ();
+ case BOOL : return input.readBool ();
+ case BYTES : return input.readBytes ();
+ case UINT32 : return input.readUInt32 ();
+ case SFIXED32: return input.readSFixed32();
+ case SFIXED64: return input.readSFixed64();
+ case SINT32 : return input.readSInt32 ();
+ case SINT64 : return input.readSInt64 ();
+
+ case STRING : return utf8Validation.readString(input);
+ case GROUP:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle nested groups.");
+ case MESSAGE:
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle embedded messages.");
+ case ENUM:
+ // We don't handle enums because we don't know what to do if the
+ // value is not recognized.
+ throw new IllegalArgumentException(
+ "readPrimitiveField() cannot handle enums.");
+ }
+
+ throw new RuntimeException(
+ "There is no way to get here, but the compiler thinks otherwise.");
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
new file mode 100644
index 0000000000..622e36a413
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -0,0 +1,549 @@
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link AbstractMessage}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class AbstractMessageTest extends TestCase {
+ /**
+ * Extends AbstractMessage and wraps some other message object. The methods
+ * of the Message interface which aren't explicitly implemented by
+ * AbstractMessage are forwarded to the wrapped object. This allows us to
+ * test that AbstractMessage's implementations work even if the wrapped
+ * object does not use them.
+ */
+ private static class AbstractMessageWrapper extends AbstractMessage {
+ private final Message wrappedMessage;
+
+ public AbstractMessageWrapper(Message wrappedMessage) {
+ this.wrappedMessage = wrappedMessage;
+ }
+
+ @Override
+ public Descriptors.Descriptor getDescriptorForType() {
+ return wrappedMessage.getDescriptorForType();
+ }
+ @Override
+ public AbstractMessageWrapper getDefaultInstanceForType() {
+ return new AbstractMessageWrapper(
+ wrappedMessage.getDefaultInstanceForType());
+ }
+ @Override
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ return wrappedMessage.getAllFields();
+ }
+ @Override
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.hasField(field);
+ }
+ @Override
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.getField(field);
+ }
+ @Override
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+ return wrappedMessage.getRepeatedFieldCount(field);
+ }
+ @Override
+ public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
+ return wrappedMessage.getRepeatedField(field, index);
+ }
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return wrappedMessage.getUnknownFields();
+ }
+ @Override
+ public Builder newBuilderForType() {
+ return new Builder(wrappedMessage.newBuilderForType());
+ }
+ @Override
+ public Builder toBuilder() {
+ return new Builder(wrappedMessage.toBuilder());
+ }
+
+ static class Builder extends AbstractMessage.Builder<Builder> {
+ private final Message.Builder wrappedBuilder;
+
+ public Builder(Message.Builder wrappedBuilder) {
+ this.wrappedBuilder = wrappedBuilder;
+ }
+
+ @Override
+ public AbstractMessageWrapper build() {
+ return new AbstractMessageWrapper(wrappedBuilder.build());
+ }
+ @Override
+ public AbstractMessageWrapper buildPartial() {
+ return new AbstractMessageWrapper(wrappedBuilder.buildPartial());
+ }
+ @Override
+ public Builder clone() {
+ return new Builder(wrappedBuilder.clone());
+ }
+ @Override
+ public boolean isInitialized() {
+ return clone().buildPartial().isInitialized();
+ }
+ @Override
+ public Descriptors.Descriptor getDescriptorForType() {
+ return wrappedBuilder.getDescriptorForType();
+ }
+ @Override
+ public AbstractMessageWrapper getDefaultInstanceForType() {
+ return new AbstractMessageWrapper(
+ wrappedBuilder.getDefaultInstanceForType());
+ }
+ @Override
+ public Map<Descriptors.FieldDescriptor, Object> getAllFields() {
+ return wrappedBuilder.getAllFields();
+ }
+ @Override
+ public Builder newBuilderForField(Descriptors.FieldDescriptor field) {
+ return new Builder(wrappedBuilder.newBuilderForField(field));
+ }
+ @Override
+ public boolean hasField(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.hasField(field);
+ }
+ @Override
+ public Object getField(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.getField(field);
+ }
+ @Override
+ public Builder setField(Descriptors.FieldDescriptor field, Object value) {
+ wrappedBuilder.setField(field, value);
+ return this;
+ }
+ @Override
+ public Builder clearField(Descriptors.FieldDescriptor field) {
+ wrappedBuilder.clearField(field);
+ return this;
+ }
+ @Override
+ public int getRepeatedFieldCount(Descriptors.FieldDescriptor field) {
+ return wrappedBuilder.getRepeatedFieldCount(field);
+ }
+ @Override
+ public Object getRepeatedField(Descriptors.FieldDescriptor field, int index) {
+ return wrappedBuilder.getRepeatedField(field, index);
+ }
+ @Override
+ public Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value) {
+ wrappedBuilder.setRepeatedField(field, index, value);
+ return this;
+ }
+ @Override
+ public Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
+ wrappedBuilder.addRepeatedField(field, value);
+ return this;
+ }
+ @Override
+ public UnknownFieldSet getUnknownFields() {
+ return wrappedBuilder.getUnknownFields();
+ }
+ @Override
+ public Builder setUnknownFields(UnknownFieldSet unknownFields) {
+ wrappedBuilder.setUnknownFields(unknownFields);
+ return this;
+ }
+ @Override
+ public Message.Builder getFieldBuilder(FieldDescriptor field) {
+ return wrappedBuilder.getFieldBuilder(field);
+ }
+ }
+ @Override
+ public Parser<? extends Message> getParserForType() {
+ return wrappedMessage.getParserForType();
+ }
+ }
+
+ // =================================================================
+
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+
+ public void testClear() throws Exception {
+ AbstractMessageWrapper message =
+ new AbstractMessageWrapper.Builder(
+ TestAllTypes.newBuilder(TestUtil.getAllSet()))
+ .clear().build();
+ TestUtil.assertClear((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testCopy() throws Exception {
+ AbstractMessageWrapper message =
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder())
+ .mergeFrom(TestUtil.getAllSet()).build();
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testSerializedSize() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+ assertEquals(message.getSerializedSize(),
+ abstractMessage.getSerializedSize());
+ }
+
+ public void testSerialization() throws Exception {
+ Message abstractMessage = new AbstractMessageWrapper(TestUtil.getAllSet());
+
+ TestUtil.assertAllFieldsSet(
+ TestAllTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getAllSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestAllTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getAllSet().toByteString()).build();
+ TestUtil.assertAllFieldsSet((TestAllTypes) message.wrappedMessage);
+ }
+
+ public void testParsingUninitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ builder.getOptionalMessageBuilder().setDummy2(10);
+ ByteString bytes = builder.buildPartial().toByteString();
+ Message.Builder abstractMessageBuilder =
+ new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
+ // mergeFrom() should not throw initialization error.
+ abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ abstractMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+
+ // test DynamicMessage directly.
+ Message.Builder dynamicMessageBuilder = DynamicMessage.newBuilder(
+ TestRequiredForeign.getDescriptor());
+ // mergeFrom() should not throw initialization error.
+ dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+ try {
+ dynamicMessageBuilder.mergeFrom(bytes).build();
+ fail();
+ } catch (UninitializedMessageException ex) {
+ // pass
+ }
+ }
+
+ public void testPackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getPackedSet());
+
+ TestUtil.assertPackedFieldsSet(
+ TestPackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getPackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testPackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedSerialization() throws Exception {
+ Message abstractMessage =
+ new AbstractMessageWrapper(TestUtil.getUnpackedSet());
+
+ TestUtil.assertUnpackedFieldsSet(
+ TestUnpackedTypes.parseFrom(abstractMessage.toByteString()));
+
+ assertEquals(TestUtil.getUnpackedSet().toByteString(),
+ abstractMessage.toByteString());
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestPackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet((TestPackedTypes) message.wrappedMessage);
+ }
+
+ public void testUnpackedParsing() throws Exception {
+ AbstractMessageWrapper.Builder builder =
+ new AbstractMessageWrapper.Builder(TestUnpackedTypes.newBuilder());
+ AbstractMessageWrapper message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(
+ (TestUnpackedTypes) message.wrappedMessage);
+ }
+
+ public void testOptimizedForSize() throws Exception {
+ // We're mostly only checking that this class was compiled successfully.
+ TestOptimizedForSize message =
+ TestOptimizedForSize.newBuilder().setI(1).build();
+ message = TestOptimizedForSize.parseFrom(message.toByteString());
+ assertEquals(2, message.getSerializedSize());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for isInitialized().
+
+ private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+ TestRequired.getDefaultInstance();
+ private static final TestRequired TEST_REQUIRED_INITIALIZED =
+ TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+ public void testIsInitialized() throws Exception {
+ TestRequired.Builder builder = TestRequired.newBuilder();
+ AbstractMessageWrapper.Builder abstractBuilder =
+ new AbstractMessageWrapper.Builder(builder);
+
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("a, b, c", abstractBuilder.getInitializationErrorString());
+ builder.setA(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("b, c", abstractBuilder.getInitializationErrorString());
+ builder.setB(1);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals("c", abstractBuilder.getInitializationErrorString());
+ builder.setC(1);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ public void testForeignIsInitialized() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+ AbstractMessageWrapper.Builder abstractBuilder =
+ new AbstractMessageWrapper.Builder(builder);
+
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "optional_message.a, optional_message.b, optional_message.c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(abstractBuilder.isInitialized());
+ assertEquals(
+ "repeated_message[0].a, repeated_message[0].b, repeated_message[0].c",
+ abstractBuilder.getInitializationErrorString());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(abstractBuilder.isInitialized());
+ assertEquals("", abstractBuilder.getInitializationErrorString());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for mergeFrom
+
+ static final TestAllTypes MERGE_SOURCE =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .build();
+
+ static final TestAllTypes MERGE_DEST =
+ TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+ .addRepeatedString("qux")
+ .build();
+
+ static final String MERGE_RESULT_TEXT =
+ "optional_int32: 1\n" +
+ "optional_int64: 2\n" +
+ "optional_string: \"foo\"\n" +
+ "optional_foreign_message {\n" +
+ " c: 3\n" +
+ "}\n" +
+ "repeated_string: \"qux\"\n" +
+ "repeated_string: \"bar\"\n";
+
+ public void testMergeFrom() throws Exception {
+ AbstractMessageWrapper result =
+ new AbstractMessageWrapper.Builder(
+ TestAllTypes.newBuilder(MERGE_DEST))
+ .mergeFrom(MERGE_SOURCE).build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ // -----------------------------------------------------------------
+ // Tests for equals and hashCode
+
+ public void testEqualsAndHashCode() throws Exception {
+ TestAllTypes a = TestUtil.getAllSet();
+ TestAllTypes b = TestAllTypes.newBuilder().build();
+ TestAllTypes c = TestAllTypes.newBuilder(b).addRepeatedString("x").build();
+ TestAllTypes d = TestAllTypes.newBuilder(c).addRepeatedString("y").build();
+ TestAllExtensions e = TestUtil.getAllExtensionsSet();
+ TestAllExtensions f = TestAllExtensions.newBuilder(e)
+ .addExtension(UnittestProto.repeatedInt32Extension, 999).build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+ checkEqualsIsConsistent(f);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(a, f);
+
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(b, f);
+
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(c, f);
+
+ checkNotEqual(d, e);
+ checkNotEqual(d, f);
+
+ checkNotEqual(e, f);
+
+ // Deserializing into the TestEmptyMessage such that every field
+ // is an {@link UnknownFieldSet.Field}.
+ UnittestProto.TestEmptyMessage eUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ UnittestProto.TestEmptyMessage fUnknownFields =
+ UnittestProto.TestEmptyMessage.parseFrom(f.toByteArray());
+ checkNotEqual(eUnknownFields, fUnknownFields);
+ checkEqualsIsConsistent(eUnknownFields);
+ checkEqualsIsConsistent(fUnknownFields);
+
+ // Subsequent reconstitutions should be identical
+ UnittestProto.TestEmptyMessage eUnknownFields2 =
+ UnittestProto.TestEmptyMessage.parseFrom(e.toByteArray());
+ checkEqualsIsConsistent(eUnknownFields, eUnknownFields2);
+ }
+
+ /**
+ * Asserts that the given proto has symmetric equals and hashCode methods.
+ */
+ private void checkEqualsIsConsistent(Message message) {
+ // Object should be equal to itself.
+ assertEquals(message, message);
+
+ // Object should be equal to a dynamic copy of itself.
+ DynamicMessage dynamic = DynamicMessage.newBuilder(message).build();
+ checkEqualsIsConsistent(message, dynamic);
+ }
+
+ /**
+ * Asserts that the given protos are equal and have the same hash code.
+ */
+ private void checkEqualsIsConsistent(Message message1, Message message2) {
+ assertEquals(message1, message2);
+ assertEquals(message2, message1);
+ assertEquals(message2.hashCode(), message1.hashCode());
+ }
+
+ /**
+ * Asserts that the given protos are not equal and have different hash codes.
+ *
+ * @warning It's valid for non-equal objects to have the same hash code, so
+ * this test is stricter than it needs to be. However, this should happen
+ * relatively rarely.
+ */
+ private void checkNotEqual(Message m1, Message m2) {
+ String equalsError = String.format("%s should not be equal to %s", m1, m2);
+ assertFalse(equalsError, m1.equals(m2));
+ assertFalse(equalsError, m2.equals(m1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", m1, m2),
+ m1.hashCode() == m2.hashCode());
+ }
+
+ public void testCheckByteStringIsUtf8OnUtf8() {
+ ByteString byteString = ByteString.copyFromUtf8("some text");
+ AbstractMessageLite.checkByteStringIsUtf8(byteString);
+ // No exception thrown.
+ }
+
+ public void testCheckByteStringIsUtf8OnNonUtf8() {
+ ByteString byteString =
+ ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+ try {
+ AbstractMessageLite.checkByteStringIsUtf8(byteString);
+ fail("Expected AbstractMessageLite.checkByteStringIsUtf8 to throw IllegalArgumentException");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AnyTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AnyTest.java
new file mode 100644
index 0000000000..cf91ed91c6
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/AnyTest.java
@@ -0,0 +1,137 @@
+// 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 any_test.AnyTestProto.TestAny;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for Any message.
+ */
+public class AnyTest extends TestCase {
+ public void testAnyGeneratedApi() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+
+
+ // Unpacking to a wrong type will throw an exception.
+ try {
+ TestAny wrongMessage = container.getValue().unpack(TestAny.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+
+ // Test that unpacking throws an exception if parsing fails.
+ TestAny.Builder containerBuilder = container.toBuilder();
+ containerBuilder.getValueBuilder().setValue(
+ ByteString.copyFrom(new byte[]{0x11}));
+ container = containerBuilder.build();
+ try {
+ TestAllTypes parsingFailed = container.getValue().unpack(TestAllTypes.class);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // expected.
+ }
+ }
+
+ public void testCustomTypeUrls() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message, "xxx.com")).build();
+
+ assertEquals(
+ "xxx.com/" + TestAllTypes.getDescriptor().getFullName(),
+ container.getValue().getTypeUrl());
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+
+ container = TestAny.newBuilder()
+ .setValue(Any.pack(message, "yyy.com/")).build();
+
+ assertEquals(
+ "yyy.com/" + TestAllTypes.getDescriptor().getFullName(),
+ container.getValue().getTypeUrl());
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+
+ container = TestAny.newBuilder()
+ .setValue(Any.pack(message, "")).build();
+
+ assertEquals(
+ "/" + TestAllTypes.getDescriptor().getFullName(),
+ container.getValue().getTypeUrl());
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+ assertFalse(container.getValue().is(TestAny.class));
+
+ result = container.getValue().unpack(TestAllTypes.class);
+ TestUtil.assertAllFieldsSet(result);
+ }
+
+ public void testCachedUnpackResult() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ TestAny container = TestAny.newBuilder()
+ .setValue(Any.pack(message)).build();
+
+ assertTrue(container.getValue().is(TestAllTypes.class));
+
+ TestAllTypes result1 = container.getValue().unpack(TestAllTypes.class);
+ TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class);
+ assertTrue(result1 == result2);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
new file mode 100644
index 0000000000..18132e9e03
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java
@@ -0,0 +1,458 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link BooleanArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class BooleanArrayListTest extends TestCase {
+
+ private static final BooleanArrayList UNARY_LIST =
+ newImmutableBooleanArrayList(true);
+ private static final BooleanArrayList TERTIARY_LIST =
+ newImmutableBooleanArrayList(true, false, true);
+
+ private BooleanArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new BooleanArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(BooleanArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(true);
+ list.addBoolean(true);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(true, false, true, false));
+ Iterator<Boolean> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(true, (boolean) list.get(0));
+ assertEquals(true, (boolean) iterator.next());
+ list.set(0, true);
+ assertEquals(false, (boolean) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, false);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(true, (boolean) TERTIARY_LIST.get(0));
+ assertEquals(false, (boolean) TERTIARY_LIST.get(1));
+ assertEquals(true, (boolean) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetBoolean() {
+ assertEquals(true, TERTIARY_LIST.getBoolean(0));
+ assertEquals(false, TERTIARY_LIST.getBoolean(1));
+ assertEquals(true, TERTIARY_LIST.getBoolean(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, BooleanArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addBoolean(true);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ list.addBoolean(false);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(true);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addBoolean(false);
+ list.addBoolean(false);
+
+ assertEquals(false, (boolean) list.set(0, true));
+ assertEquals(true, list.getBoolean(0));
+
+ assertEquals(false, (boolean) list.set(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.set(-1, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetBoolean() {
+ list.addBoolean(true);
+ list.addBoolean(true);
+
+ assertEquals(true, list.setBoolean(0, false));
+ assertEquals(false, list.getBoolean(0));
+
+ assertEquals(true, list.setBoolean(1, false));
+ assertEquals(false, list.getBoolean(1));
+
+ try {
+ list.setBoolean(-1, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(2, false);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(false));
+ assertEquals(asList(false), list);
+
+ assertTrue(list.add(true));
+ list.add(0, false);
+ assertEquals(asList(false, false, true), list);
+
+ list.add(0, true);
+ list.add(0, false);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(i % 2 == 0);
+ }
+ assertEquals(
+ asList(false, true, false, false, true, true, false, true, false, true, false),
+ list);
+
+ try {
+ list.add(-1, true);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, true);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddBoolean() {
+ assertEquals(0, list.size());
+
+ list.addBoolean(false);
+ assertEquals(asList(false), list);
+
+ list.addBoolean(true);
+ assertEquals(asList(false, true), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(true)));
+ assertEquals(1, list.size());
+ assertEquals(true, (boolean) list.get(0));
+ assertEquals(true, list.getBoolean(0));
+
+ assertTrue(list.addAll(asList(false, true, false, true, false)));
+ assertEquals(asList(true, false, true, false, true, false), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(true, false, true, false, true, false, true, false, true), list);
+
+ assertFalse(list.addAll(Collections.<Boolean>emptyList()));
+ assertFalse(list.addAll(BooleanArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(true, (boolean) list.remove(0));
+ assertEquals(asList(false, true), list);
+
+ assertTrue(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertFalse(list.remove(Boolean.TRUE));
+ assertEquals(asList(false), list);
+
+ assertEquals(false, (boolean) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(BooleanArrayList list) {
+
+ try {
+ list.add(true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, true);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(true));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new BooleanArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(true));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addBoolean(false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(Boolean.TRUE));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Boolean>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(Boolean.TRUE));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setBoolean(0, false);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) {
+ BooleanArrayList list = new BooleanArrayList();
+ for (boolean element : elements) {
+ list.addBoolean(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
new file mode 100644
index 0000000000..db10ee7483
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java
@@ -0,0 +1,100 @@
+// 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.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * This class tests {@link BoundedByteString}, which extends {@link LiteralByteString},
+ * by inheriting the tests from {@link LiteralByteStringTest}. The only method which
+ * is strange enough that it needs to be overridden here is {@link #testToString()}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class BoundedByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "BoundedByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(2341, 11337766L);
+ int from = 100;
+ int to = sourceBytes.length - 100;
+ stringUnderTest = ByteString.copyFrom(sourceBytes).substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = 727575887;
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ 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));
+
+ String roundTripString = chopped.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString.substring(2, testString.length() - 6), roundTripString);
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ 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));
+
+ String roundTripString = chopped.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString.substring(2, testString.length() - 6), roundTripString);
+ }
+
+ @Override
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java
new file mode 100644
index 0000000000..6b1cfe78c1
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java
@@ -0,0 +1,80 @@
+// 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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Random;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link ByteBufferWriter}.
+ */
+public class ByteBufferWriterTest extends TestCase {
+
+ public void testHeapBuffer() throws IOException {
+ // Test a small and large buffer.
+ testWrite(ByteBuffer.allocate(100));
+ testWrite(ByteBuffer.allocate(1024 * 100));
+ }
+
+ public void testDirectBuffer() throws IOException {
+ // Test a small and large buffer.
+ testWrite(ByteBuffer.allocateDirect(100));
+ testWrite(ByteBuffer.allocateDirect(1024 * 100));
+ }
+
+ private void testWrite(ByteBuffer buffer) throws IOException {
+ fillRandom(buffer);
+ ByteArrayOutputStream os = new ByteArrayOutputStream(buffer.remaining());
+ ByteBufferWriter.write(buffer, os);
+ assertEquals(0, buffer.position());
+ assertTrue(Arrays.equals(toArray(buffer), os.toByteArray()));
+ }
+
+ private void fillRandom(ByteBuffer buf) {
+ byte[] bytes = new byte[buf.remaining()];
+ new Random().nextBytes(bytes);
+ buf.put(bytes);
+ buf.flip();
+ return;
+ }
+
+ private byte[] toArray(ByteBuffer buf) {
+ int originalPosition = buf.position();
+ byte[] bytes = new byte[buf.remaining()];
+ buf.get(bytes);
+ buf.position(originalPosition);
+ return bytes;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteStringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
new file mode 100644
index 0000000000..be71f1f5a3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ByteStringTest.java
@@ -0,0 +1,772 @@
+// 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 com.google.protobuf.ByteString.Output;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Random;
+import junit.framework.TestCase;
+
+/**
+ * Test methods with implementations in {@link ByteString}, plus do some top-level "integration"
+ * tests.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class ByteStringTest extends TestCase {
+
+ private static final Charset UTF_16 = Charset.forName("UTF-16");
+
+ static byte[] getTestBytes(int size, long seed) {
+ Random random = new Random(seed);
+ byte[] result = new byte[size];
+ random.nextBytes(result);
+ return result;
+ }
+
+ private byte[] getTestBytes(int size) {
+ return getTestBytes(size, 445566L);
+ }
+
+ private byte[] getTestBytes() {
+ return getTestBytes(1000);
+ }
+
+ // Compare the entire left array with a subset of the right array.
+ private boolean isArrayRange(byte[] left, byte[] right, int rightOffset, int length) {
+ boolean stillEqual = (left.length == length);
+ for (int i = 0; (stillEqual && i < length); ++i) {
+ stillEqual = (left[i] == right[rightOffset + i]);
+ }
+ return stillEqual;
+ }
+
+ // Returns true only if the given two arrays have identical contents.
+ private boolean isArray(byte[] left, byte[] right) {
+ return left.length == right.length && isArrayRange(left, right, 0, left.length);
+ }
+
+ public void testSubstring_BeginIndex() {
+ byte[] bytes = getTestBytes();
+ ByteString substring = ByteString.copyFrom(bytes).substring(500);
+ assertTrue("substring must contain the tail of the string",
+ isArrayRange(substring.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_BytesOffsetSize() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes, 500, 200);
+ assertTrue("copyFrom sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_Bytes() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ assertTrue("copyFrom must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ public void testCopyFrom_ByteBufferSize() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer, 200);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, 200));
+ }
+
+ public void testCopyFrom_ByteBuffer() {
+ byte[] bytes = getTestBytes();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(bytes.length);
+ byteBuffer.put(bytes);
+ byteBuffer.position(500);
+ ByteString byteString = ByteString.copyFrom(byteBuffer);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), bytes, 500, bytes.length - 500));
+ }
+
+ public void testCopyFrom_StringEncoding() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFrom(testString, UTF_16);
+ byte[] testBytes = testString.getBytes(UTF_16);
+ assertTrue("copyFrom string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Utf8() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString byteString = ByteString.copyFromUtf8(testString);
+ byte[] testBytes = testString.getBytes(Internal.UTF_8);
+ assertTrue("copyFromUtf8 string must respect the charset",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ }
+
+ public void testCopyFrom_Iterable() {
+ byte[] testBytes = getTestBytes(77777, 113344L);
+ final List<ByteString> pieces = makeConcretePieces(testBytes);
+ // Call copyFrom() on a Collection
+ ByteString byteString = ByteString.copyFrom(pieces);
+ assertTrue("copyFrom a List must contain the expected bytes",
+ isArrayRange(byteString.toByteArray(), testBytes, 0, testBytes.length));
+ // Call copyFrom on an iteration that's not a collection
+ ByteString byteStringAlt = ByteString.copyFrom(new Iterable<ByteString>() {
+ @Override
+ public Iterator<ByteString> iterator() {
+ return pieces.iterator();
+ }
+ });
+ assertEquals("copyFrom from an Iteration must contain the expected bytes",
+ byteString, byteStringAlt);
+ }
+
+ public void testCopyTo_TargetOffset() {
+ byte[] bytes = getTestBytes();
+ ByteString byteString = ByteString.copyFrom(bytes);
+ byte[] target = new byte[bytes.length + 1000];
+ byteString.copyTo(target, 400);
+ assertTrue("copyFrom byteBuffer sub-range must contain the expected bytes",
+ isArrayRange(bytes, target, 400, bytes.length));
+ }
+
+ public void testReadFrom_emptyStream() throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(new byte[0]));
+ assertSame("reading an empty stream must result in the EMPTY constant "
+ + "byte string", ByteString.EMPTY, byteString);
+ }
+
+ public void testReadFrom_smallStream() throws IOException {
+ assertReadFrom(getTestBytes(10));
+ }
+
+ public void testReadFrom_mutating() throws IOException {
+ byte[] capturedArray = null;
+ EvilInputStream eis = new EvilInputStream();
+ ByteString byteString = ByteString.readFrom(eis);
+
+ capturedArray = eis.capturedArray;
+ byte[] originalValue = byteString.toByteArray();
+ for (int x = 0; x < capturedArray.length; ++x) {
+ capturedArray[x] = (byte) 0;
+ }
+
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("copyFrom byteBuffer must not grant access to underlying array",
+ Arrays.equals(originalValue, newValue));
+ }
+
+ // Tests sizes that are near the rope copy-out threshold.
+ public void testReadFrom_mediumStream() throws IOException {
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE - 1));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE));
+ assertReadFrom(getTestBytes(ByteString.CONCATENATE_BY_COPY_SIZE + 1));
+ assertReadFrom(getTestBytes(200));
+ }
+
+ // Tests sizes that are over multi-segment rope threshold.
+ public void testReadFrom_largeStream() throws IOException {
+ assertReadFrom(getTestBytes(0x100));
+ assertReadFrom(getTestBytes(0x101));
+ assertReadFrom(getTestBytes(0x110));
+ assertReadFrom(getTestBytes(0x1000));
+ assertReadFrom(getTestBytes(0x1001));
+ assertReadFrom(getTestBytes(0x1010));
+ assertReadFrom(getTestBytes(0x10000));
+ assertReadFrom(getTestBytes(0x10001));
+ assertReadFrom(getTestBytes(0x10010));
+ }
+
+ // Tests sizes that are near the read buffer size.
+ public void testReadFrom_byteBoundaries() throws IOException {
+ final int min = ByteString.MIN_READ_FROM_CHUNK_SIZE;
+ final int max = ByteString.MAX_READ_FROM_CHUNK_SIZE;
+
+ assertReadFrom(getTestBytes(min - 1));
+ assertReadFrom(getTestBytes(min));
+ assertReadFrom(getTestBytes(min + 1));
+
+ assertReadFrom(getTestBytes(min * 2 - 1));
+ assertReadFrom(getTestBytes(min * 2));
+ assertReadFrom(getTestBytes(min * 2 + 1));
+
+ assertReadFrom(getTestBytes(min * 4 - 1));
+ assertReadFrom(getTestBytes(min * 4));
+ assertReadFrom(getTestBytes(min * 4 + 1));
+
+ assertReadFrom(getTestBytes(min * 8 - 1));
+ assertReadFrom(getTestBytes(min * 8));
+ assertReadFrom(getTestBytes(min * 8 + 1));
+
+ assertReadFrom(getTestBytes(max - 1));
+ assertReadFrom(getTestBytes(max));
+ assertReadFrom(getTestBytes(max + 1));
+
+ assertReadFrom(getTestBytes(max * 2 - 1));
+ assertReadFrom(getTestBytes(max * 2));
+ assertReadFrom(getTestBytes(max * 2 + 1));
+ }
+
+ // Tests that IOExceptions propagate through ByteString.readFrom().
+ public void testReadFrom_IOExceptions() {
+ try {
+ ByteString.readFrom(new FailStream());
+ fail("readFrom must throw the underlying IOException");
+
+ } catch (IOException e) {
+ assertEquals("readFrom must throw the expected exception",
+ "synthetic failure", e.getMessage());
+ }
+ }
+
+ // Tests that ByteString.readFrom works with streams that don't
+ // always fill their buffers.
+ public void testReadFrom_reluctantStream() throws IOException {
+ final byte[] data = getTestBytes(0x1000);
+
+ ByteString byteString = ByteString.readFrom(new ReluctantStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+
+ // Same test as above, but with some specific chunk sizes.
+ assertReadFromReluctantStream(data, 100);
+ assertReadFromReluctantStream(data, 248);
+ assertReadFromReluctantStream(data, 249);
+ assertReadFromReluctantStream(data, 250);
+ assertReadFromReluctantStream(data, 251);
+ assertReadFromReluctantStream(data, 0x1000);
+ assertReadFromReluctantStream(data, 0x1001);
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly from a
+ // reluctant stream with the given chunkSize parameter.
+ private void assertReadFromReluctantStream(byte[] bytes, int chunkSize)
+ throws IOException {
+ ByteString b = ByteString.readFrom(new ReluctantStream(bytes), chunkSize);
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(b.toByteArray(), bytes));
+ }
+
+ // Tests that ByteString.readFrom works with streams that implement
+ // available().
+ public void testReadFrom_available() throws IOException {
+ final byte[] data = getTestBytes(0x1001);
+
+ ByteString byteString = ByteString.readFrom(new AvailableStream(data));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), data));
+ }
+
+ // Fails unless ByteString.readFrom reads the bytes correctly.
+ private void assertReadFrom(byte[] bytes) throws IOException {
+ ByteString byteString =
+ ByteString.readFrom(new ByteArrayInputStream(bytes));
+ assertTrue("readFrom byte stream must contain the expected bytes",
+ isArray(byteString.toByteArray(), bytes));
+ }
+
+ // A stream that fails when read.
+ private static final class FailStream extends InputStream {
+ @Override public int read() throws IOException {
+ throw new IOException("synthetic failure");
+ }
+ }
+
+ // A stream that simulates blocking by only producing 250 characters
+ // per call to read(byte[]).
+ private static class ReluctantStream extends InputStream {
+ protected final byte[] data;
+ protected int pos = 0;
+
+ public ReluctantStream(byte[] data) {
+ this.data = data;
+ }
+
+ @Override public int read() {
+ if (pos == data.length) {
+ return -1;
+ } else {
+ return data[pos++];
+ }
+ }
+
+ @Override public int read(byte[] buf) {
+ return read(buf, 0, buf.length);
+ }
+
+ @Override public int read(byte[] buf, int offset, int size) {
+ if (pos == data.length) {
+ return -1;
+ }
+ int count = Math.min(Math.min(size, data.length - pos), 250);
+ System.arraycopy(data, pos, buf, offset, count);
+ pos += count;
+ return count;
+ }
+ }
+
+ // Same as above, but also implements available().
+ private static final class AvailableStream extends ReluctantStream {
+ public AvailableStream(byte[] data) {
+ super(data);
+ }
+
+ @Override public int available() {
+ return Math.min(250, data.length - pos);
+ }
+ }
+
+ // A stream which exposes the byte array passed into read(byte[], int, int).
+ private static class EvilInputStream extends InputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public int read(byte[] buf, int off, int len) {
+ if (capturedArray != null) {
+ return -1;
+ } else {
+ capturedArray = buf;
+ for (int x = 0; x < len; ++x) {
+ buf[x] = (byte) x;
+ }
+ return len;
+ }
+ }
+
+ @Override
+ public int read() {
+ // Purposefully do nothing.
+ return -1;
+ }
+ }
+
+ // A stream which exposes the byte array passed into write(byte[], int, int).
+ private static class EvilOutputStream extends OutputStream {
+ public byte[] capturedArray = null;
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ if (capturedArray == null) {
+ capturedArray = buf;
+ }
+ }
+
+ @Override
+ public void write(int ignored) {
+ // Purposefully do nothing.
+ }
+ }
+
+ public void testToStringUtf8() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ byte[] testBytes = testString.getBytes(Internal.UTF_8);
+ ByteString byteString = ByteString.copyFrom(testBytes);
+ assertEquals("copyToStringUtf8 must respect the charset",
+ testString, byteString.toStringUtf8());
+ }
+
+ public void testNewOutput_InitialCapacity() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.Output output = ByteString.newOutput(bytes.length + 100);
+ output.write(bytes);
+ ByteString byteString = output.toByteString();
+ assertTrue(
+ "String built from newOutput(int) must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ // Test newOutput() using a variety of buffer sizes and a variety of (fixed)
+ // write sizes
+ public void testNewOutput_ArrayWrite() {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {128, 256, length / 2, length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ int[] writeSizes = {1, 4, 5, 7, 23, bytes.length};
+
+ for (int bufferSize : bufferSizes) {
+ for (int writeSize : writeSizes) {
+ // Test writing the entire output writeSize bytes at a time.
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (int i = 0; i < length; i += writeSize) {
+ output.write(bytes, i, Math.min(writeSize, length - i));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+ }
+
+ // Test newOutput() using a variety of buffer sizes, but writing all the
+ // characters using write(byte);
+ public void testNewOutput_WriteChar() {
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+ for (int bufferSize : bufferSizes) {
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ for (byte byteValue : bytes) {
+ output.write(byteValue);
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ // Test newOutput() in which we write the bytes using a variety of methods
+ // and sizes, and in which we repeatedly call toByteString() in the middle.
+ public void testNewOutput_Mixed() {
+ Random rng = new Random(1);
+ byte[] bytes = getTestBytes();
+ int length = bytes.length;
+ int[] bufferSizes = {0, 1, 128, 256, length / 2,
+ length - 1, length, length + 1,
+ 2 * length, 3 * length};
+
+ for (int bufferSize : bufferSizes) {
+ // Test writing the entire output using a mixture of write sizes and
+ // methods;
+ ByteString.Output output = ByteString.newOutput(bufferSize);
+ int position = 0;
+ while (position < bytes.length) {
+ if (rng.nextBoolean()) {
+ int count = 1 + rng.nextInt(bytes.length - position);
+ output.write(bytes, position, count);
+ position += count;
+ } else {
+ output.write(bytes[position]);
+ position++;
+ }
+ assertEquals("size() returns the right value", position, output.size());
+ assertTrue("newOutput() substring must have correct bytes",
+ isArrayRange(output.toByteString().toByteArray(),
+ bytes, 0, position));
+ }
+ ByteString byteString = output.toByteString();
+ assertTrue("String built from newOutput() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+ }
+
+ public void testNewOutputEmpty() {
+ // Make sure newOutput() correctly builds empty byte strings
+ ByteString byteString = ByteString.newOutput().toByteString();
+ assertEquals(ByteString.EMPTY, byteString);
+ }
+
+ public void testNewOutput_Mutating() throws IOException {
+ Output os = ByteString.newOutput(5);
+ os.write(new byte[] {1, 2, 3, 4, 5});
+ EvilOutputStream eos = new EvilOutputStream();
+ os.writeTo(eos);
+ byte[] capturedArray = eos.capturedArray;
+ ByteString byteString = os.toByteString();
+ byte[] oldValue = byteString.toByteArray();
+ Arrays.fill(capturedArray, (byte) 0);
+ byte[] newValue = byteString.toByteArray();
+ assertTrue("Output must not provide access to the underlying byte array",
+ Arrays.equals(oldValue, newValue));
+ }
+
+ public void testNewCodedBuilder() throws IOException {
+ byte[] bytes = getTestBytes();
+ ByteString.CodedBuilder builder = ByteString.newCodedBuilder(bytes.length);
+ builder.getCodedOutput().writeRawBytes(bytes);
+ ByteString byteString = builder.build();
+ assertTrue("String built from newCodedBuilder() must contain the expected bytes",
+ isArrayRange(bytes, byteString.toByteArray(), 0, bytes.length));
+ }
+
+ public void testSubstringParity() {
+ byte[] bigBytes = getTestBytes(2048 * 1024, 113344L);
+ int start = 512 * 1024 - 3333;
+ int end = 512 * 1024 + 7777;
+ ByteString concreteSubstring = ByteString.copyFrom(bigBytes).substring(start, end);
+ boolean ok = true;
+ for (int i = start; ok && i < end; ++i) {
+ ok = (bigBytes[i] == concreteSubstring.byteAt(i - start));
+ }
+ assertTrue("Concrete substring didn't capture the right bytes", ok);
+
+ ByteString literalString = ByteString.copyFrom(bigBytes, start, end - start);
+ assertTrue("Substring must be equal to literal string",
+ concreteSubstring.equals(literalString));
+ assertEquals("Substring must have same hashcode as literal string",
+ literalString.hashCode(), concreteSubstring.hashCode());
+ }
+
+ public void testCompositeSubstring() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ int from = 1000;
+ int to = 40000;
+ ByteString compositeSubstring = listString.substring(from, to);
+ byte[] substringBytes = compositeSubstring.toByteArray();
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == substringBytes[i];
+ }
+ assertTrue("Substring must return correct bytes", stillEqual);
+
+ stillEqual = true;
+ for (int i = 0; stillEqual && i < to - from; ++i) {
+ stillEqual = referenceBytes[from + i] == compositeSubstring.byteAt(i);
+ }
+ assertTrue("Substring must support byteAt() correctly", stillEqual);
+
+ ByteString literalSubstring = ByteString.copyFrom(referenceBytes, from, to - from);
+ assertTrue("Composite substring must equal a literal substring over the same bytes",
+ compositeSubstring.equals(literalSubstring));
+ assertTrue("Literal substring must equal a composite substring over the same bytes",
+ literalSubstring.equals(compositeSubstring));
+
+ assertEquals("We must get the same hashcodes for composite and literal substrings",
+ literalSubstring.hashCode(), compositeSubstring.hashCode());
+
+ assertFalse("We can't be equal to a proper substring",
+ compositeSubstring.equals(literalSubstring.substring(0, literalSubstring.size() - 1)));
+ }
+
+ public void testCopyFromList() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+ ByteString listString = ByteString.copyFrom(pieces);
+
+ assertTrue("Composite string must be equal to literal string",
+ listString.equals(literalString));
+ assertEquals("Composite string must have same hashcode as literal string",
+ literalString.hashCode(), listString.hashCode());
+ }
+
+ public void testConcat() {
+ byte[] referenceBytes = getTestBytes(77748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ List<ByteString> pieces = makeConcretePieces(referenceBytes);
+
+ Iterator<ByteString> iter = pieces.iterator();
+ ByteString concatenatedString = iter.next();
+ while (iter.hasNext()) {
+ concatenatedString = concatenatedString.concat(iter.next());
+ }
+
+ assertTrue("Concatenated string must be equal to literal string",
+ concatenatedString.equals(literalString));
+ assertEquals("Concatenated string must have same hashcode as literal string",
+ literalString.hashCode(), concatenatedString.hashCode());
+ }
+
+ /**
+ * Test the Rope implementation can deal with Empty nodes, even though we
+ * guard against them. See also {@link LiteralByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ byte[] referenceBytes = getTestBytes(7748, 113344L);
+ ByteString literalString = ByteString.copyFrom(referenceBytes);
+
+ ByteString duo = RopeByteString.newInstanceForTest(literalString, literalString);
+ ByteString temp = RopeByteString.newInstanceForTest(
+ RopeByteString.newInstanceForTest(literalString, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, literalString));
+ ByteString quintet = RopeByteString.newInstanceForTest(temp, ByteString.EMPTY);
+
+ assertTrue("String with concatenated nulls must equal simple concatenate",
+ duo.equals(quintet));
+ assertEquals("String with concatenated nulls have same hashcode as simple concatenate",
+ duo.hashCode(), quintet.hashCode());
+
+ ByteString.ByteIterator duoIter = duo.iterator();
+ ByteString.ByteIterator quintetIter = quintet.iterator();
+ boolean stillEqual = true;
+ while (stillEqual && quintetIter.hasNext()) {
+ stillEqual = (duoIter.nextByte() == quintetIter.nextByte());
+ }
+ assertTrue("We must get the same characters by iterating", stillEqual);
+ assertFalse("Iterator must be exhausted", duoIter.hasNext());
+ try {
+ duoIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ try {
+ quintetIter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+
+ // Test that even if we force empty strings in as rope leaves in this
+ // configuration, we always get a (possibly Bounded) LiteralByteString
+ // for a length 1 substring.
+ //
+ // It is possible, using the testing factory method to create deeply nested
+ // 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 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 ByteString.LeafByteString);
+ }
+ }
+
+ public void testStartsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.startsWith(ByteString.EMPTY));
+ assertTrue(string.startsWith(string));
+ assertTrue(string.startsWith(prefix));
+ assertFalse(string.startsWith(suffix));
+ assertFalse(prefix.startsWith(suffix));
+ assertFalse(suffix.startsWith(prefix));
+ assertFalse(ByteString.EMPTY.startsWith(prefix));
+ assertTrue(ByteString.EMPTY.startsWith(ByteString.EMPTY));
+ }
+
+ public void testEndsWith() {
+ byte[] bytes = getTestBytes(1000, 1234L);
+ ByteString string = ByteString.copyFrom(bytes);
+ ByteString prefix = ByteString.copyFrom(bytes, 0, 500);
+ ByteString suffix = ByteString.copyFrom(bytes, 400, 600);
+ assertTrue(string.endsWith(ByteString.EMPTY));
+ assertTrue(string.endsWith(string));
+ assertTrue(string.endsWith(suffix));
+ assertFalse(string.endsWith(prefix));
+ assertFalse(suffix.endsWith(prefix));
+ assertFalse(prefix.endsWith(suffix));
+ assertFalse(ByteString.EMPTY.endsWith(suffix));
+ assertTrue(ByteString.EMPTY.endsWith(ByteString.EMPTY));
+ }
+
+ static List<ByteString> makeConcretePieces(byte[] referenceBytes) {
+ List<ByteString> pieces = new ArrayList<ByteString>();
+ // Starting length should be small enough that we'll do some concatenating by
+ // copying if we just concatenate all these pieces together.
+ for (int start = 0, length = 16; start < referenceBytes.length; start += length) {
+ length = (length << 1) - 1;
+ if (start + length > referenceBytes.length) {
+ length = referenceBytes.length - start;
+ }
+ pieces.add(ByteString.copyFrom(referenceBytes, start, length));
+ }
+ return pieces;
+ }
+
+ private byte[] substringUsingWriteTo(
+ ByteString data, int offset, int length) throws IOException {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ data.writeTo(output, offset, length);
+ return output.toByteArray();
+ }
+
+ public void testWriteToOutputStream() throws Exception {
+ // Choose a size large enough so when two ByteStrings are concatenated they
+ // won't be merged into one byte array due to some optimizations.
+ final int dataSize = ByteString.CONCATENATE_BY_COPY_SIZE + 1;
+ byte[] data1 = new byte[dataSize];
+ for (int i = 0; i < data1.length; i++) {
+ data1[i] = (byte) 1;
+ }
+ data1[1] = (byte) 11;
+ // Test LiteralByteString.writeTo(OutputStream,int,int)
+ ByteString left = ByteString.wrap(data1);
+ byte[] result = substringUsingWriteTo(left, 1, 1);
+ assertEquals(1, result.length);
+ assertEquals((byte) 11, result[0]);
+
+ byte[] data2 = new byte[dataSize];
+ for (int i = 0; i < data1.length; i++) {
+ data2[i] = (byte) 2;
+ }
+ 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
+ // structure.
+ assertEquals(1, root.getTreeDepth());
+ // Write parts of the left node.
+ result = substringUsingWriteTo(root, 0, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 1, result[0]);
+ assertEquals((byte) 1, result[dataSize - 1]);
+ // Write parts of the right node.
+ result = substringUsingWriteTo(root, dataSize, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 2, result[0]);
+ assertEquals((byte) 2, result[dataSize - 1]);
+ // Write a segment of bytes that runs across both nodes.
+ result = substringUsingWriteTo(root, dataSize / 2, dataSize);
+ assertEquals(dataSize, result.length);
+ assertEquals((byte) 1, result[0]);
+ assertEquals((byte) 1, result[dataSize - dataSize / 2 - 1]);
+ assertEquals((byte) 2, result[dataSize - dataSize / 2]);
+ assertEquals((byte) 2, result[dataSize - 1]);
+ }
+
+ /**
+ * Tests ByteString uses Arrays based byte copier when running under Hotstop VM.
+ */
+ public void testByteArrayCopier() throws Exception {
+ Field field = ByteString.class.getDeclaredField("byteArrayCopier");
+ field.setAccessible(true);
+ Object byteArrayCopier = field.get(null);
+ assertNotNull(byteArrayCopier);
+ assertTrue(
+ byteArrayCopier.toString(),
+ byteArrayCopier.getClass().getSimpleName().endsWith("ArraysByteArrayCopier"));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
new file mode 100644
index 0000000000..cc65d19ab7
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java
@@ -0,0 +1,141 @@
+// 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 proto2_test_check_utf8.TestCheckUtf8.BytesWrapper;
+import proto2_test_check_utf8.TestCheckUtf8.StringWrapper;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.BytesWrapperSize;
+import proto2_test_check_utf8_size.TestCheckUtf8Size.StringWrapperSize;
+
+import junit.framework.TestCase;
+
+/**
+ * Test that protos generated with file option java_string_check_utf8 do in
+ * fact perform appropriate UTF-8 checks.
+ *
+ * @author jbaum@google.com (Jacob Butcher)
+ */
+public class CheckUtf8Test extends TestCase {
+
+ private static final String UTF8_BYTE_STRING_TEXT = "some text";
+ private static final ByteString UTF8_BYTE_STRING =
+ ByteString.copyFromUtf8(UTF8_BYTE_STRING_TEXT);
+ private static final ByteString NON_UTF8_BYTE_STRING =
+ ByteString.copyFrom(new byte[]{(byte) 0x80}); // A lone continuation byte.
+
+ public void testBuildRequiredStringWithGoodUtf8() throws Exception {
+ assertEquals(UTF8_BYTE_STRING_TEXT,
+ StringWrapper.newBuilder().setReqBytes(UTF8_BYTE_STRING).getReq());
+ }
+
+ public void testParseRequiredStringWithGoodUtf8() throws Exception {
+ ByteString serialized =
+ BytesWrapper.newBuilder().setReq(UTF8_BYTE_STRING).build().toByteString();
+ assertEquals(UTF8_BYTE_STRING_TEXT, StringWrapper.parser().parseFrom(serialized).getReq());
+ }
+
+ public void testBuildRequiredStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildOptionalStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRepeatedStringWithBadUtf8() throws Exception {
+ try {
+ StringWrapper.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testParseRequiredStringWithBadUtf8() throws Exception {
+ ByteString serialized =
+ BytesWrapper.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+ try {
+ StringWrapper.parser().parseFrom(serialized);
+ fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRequiredStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().setReqBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildOptionalStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().setOptBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testBuildRepeatedStringWithBadUtf8Size() throws Exception {
+ try {
+ StringWrapperSize.newBuilder().addRepBytes(NON_UTF8_BYTE_STRING);
+ fail("Expected IllegalArgumentException for non UTF-8 byte string.");
+ } catch (IllegalArgumentException exception) {
+ assertEquals("Byte string is not UTF-8.", exception.getMessage());
+ }
+ }
+
+ public void testParseRequiredStringWithBadUtf8Size() throws Exception {
+ ByteString serialized =
+ BytesWrapperSize.newBuilder().setReq(NON_UTF8_BYTE_STRING).build().toByteString();
+ try {
+ StringWrapperSize.parser().parseFrom(serialized);
+ fail("Expected InvalidProtocolBufferException for non UTF-8 byte string.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals("Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
new file mode 100644
index 0000000000..e440c7db3d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -0,0 +1,971 @@
+// 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 protobuf_unittest.UnittestProto.BoolMessage;
+import protobuf_unittest.UnittestProto.Int32Message;
+import protobuf_unittest.UnittestProto.Int64Message;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRecursiveMessage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link CodedInputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedInputStreamTest extends TestCase {
+ private enum InputType {
+ ARRAY {
+ @Override
+ CodedInputStream newDecoder(byte[] data, int blockSize) {
+ return CodedInputStream.newInstance(data);
+ }
+ },
+ NIO_HEAP {
+ @Override
+ CodedInputStream newDecoder(byte[] data, int blockSize) {
+ return CodedInputStream.newInstance(ByteBuffer.wrap(data));
+ }
+ },
+ NIO_DIRECT {
+ @Override
+ CodedInputStream newDecoder(byte[] data, int blockSize) {
+ ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
+ buffer.put(data);
+ buffer.flip();
+ return CodedInputStream.newInstance(buffer);
+ }
+ },
+ STREAM {
+ @Override
+ CodedInputStream newDecoder(byte[] data, int blockSize) {
+ return CodedInputStream.newInstance(new SmallBlockInputStream(data, blockSize));
+ }
+ };
+
+ CodedInputStream newDecoder(byte[] data) {
+ return newDecoder(data, data.length);
+ }
+
+ abstract CodedInputStream newDecoder(byte[] data, int blockSize);
+ }
+
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are actually ints so that I
+ * can use hex notation and not get stupid errors about precision.
+ */
+ private byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /**
+ * An InputStream which limits the number of bytes it reads at a time. We use this to make sure
+ * that CodedInputStream doesn't screw up when reading in small blocks.
+ */
+ private static final class SmallBlockInputStream extends FilterInputStream {
+ private final int blockSize;
+
+ public SmallBlockInputStream(byte[] data, int blockSize) {
+ super(new ByteArrayInputStream(data));
+ this.blockSize = blockSize;
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return super.read(b, 0, Math.min(b.length, blockSize));
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return super.read(b, off, Math.min(len, blockSize));
+ }
+ }
+
+ private void assertDataConsumed(String msg, byte[] data, CodedInputStream input)
+ throws IOException {
+ assertEquals(msg, data.length, input.getTotalBytesRead());
+ assertTrue(msg, input.isAtEnd());
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and checks that the result
+ * matches the given value.
+ */
+ private void assertReadVarint(byte[] data, long value) throws Exception {
+ for (InputType inputType : InputType.values()) {
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ CodedInputStream input = inputType.newDecoder(data, blockSize);
+ assertEquals(inputType.name(), (int) value, input.readRawVarint32());
+ assertDataConsumed(inputType.name(), data, input);
+
+ input = inputType.newDecoder(data, blockSize);
+ assertEquals(inputType.name(), value, input.readRawVarint64());
+ assertDataConsumed(inputType.name(), data, input);
+
+ input = inputType.newDecoder(data, blockSize);
+ assertEquals(inputType.name(), value, input.readRawVarint64SlowPath());
+ assertDataConsumed(inputType.name(), data, input);
+
+ input = inputType.newDecoder(data, blockSize);
+ assertTrue(inputType.name(), input.skipField(WireFormat.WIRETYPE_VARINT));
+ assertDataConsumed(inputType.name(), data, input);
+ }
+ }
+
+ // Try reading direct from an InputStream. We want to verify that it
+ // doesn't read past the end of the input, so we copy to a new, bigger
+ // array first.
+ byte[] longerData = new byte[data.length + 1];
+ System.arraycopy(data, 0, longerData, 0, data.length);
+ InputStream rawInput = new ByteArrayInputStream(longerData);
+ assertEquals((int) value, CodedInputStream.readRawVarint32(rawInput));
+ assertEquals(1, rawInput.available());
+ }
+
+ /**
+ * Parses the given bytes using readRawVarint32() and readRawVarint64() and expects them to fail
+ * with an InvalidProtocolBufferException whose description matches the given one.
+ */
+ private void assertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
+ throws Exception {
+ for (InputType inputType : InputType.values()) {
+ try {
+ CodedInputStream input = inputType.newDecoder(data);
+ input.readRawVarint32();
+ fail(inputType.name() + ": Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(inputType.name(), expected.getMessage(), e.getMessage());
+ }
+ try {
+ CodedInputStream input = inputType.newDecoder(data);
+ input.readRawVarint64();
+ fail(inputType.name() + ": Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(inputType.name(), expected.getMessage(), e.getMessage());
+ }
+ }
+
+ // Make sure we get the same error when reading direct from an InputStream.
+ try {
+ CodedInputStream.readRawVarint32(new ByteArrayInputStream(data));
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(expected.getMessage(), e.getMessage());
+ }
+ }
+
+ /** Tests readRawVarint32() and readRawVarint64(). */
+ public void testReadVarint() throws Exception {
+ assertReadVarint(bytes(0x00), 0);
+ assertReadVarint(bytes(0x01), 1);
+ assertReadVarint(bytes(0x7f), 127);
+ // 14882
+ assertReadVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertReadVarint(
+ bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertReadVarint(
+ bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bL << 28));
+ // 41256202580718336
+ assertReadVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0)
+ | (0x66 << 7)
+ | (0x6b << 14)
+ | (0x1c << 21)
+ | (0x43L << 28)
+ | (0x49L << 35)
+ | (0x24L << 42)
+ | (0x49L << 49));
+ // 11964378330978735131
+ assertReadVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0)
+ | (0x28 << 7)
+ | (0x79 << 14)
+ | (0x42 << 21)
+ | (0x3bL << 28)
+ | (0x56L << 35)
+ | (0x00L << 42)
+ | (0x05L << 49)
+ | (0x26L << 56)
+ | (0x01L << 63));
+
+ // Failures
+ assertReadVarintFailure(
+ InvalidProtocolBufferException.malformedVarint(),
+ bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00));
+ assertReadVarintFailure(InvalidProtocolBufferException.truncatedMessage(), bytes(0x80));
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian32() and checks that the result matches the
+ * given value.
+ */
+ private void assertReadLittleEndian32(byte[] data, int value) throws Exception {
+ for (InputType inputType : InputType.values()) {
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ CodedInputStream input = inputType.newDecoder(data, blockSize);
+ assertEquals(inputType.name(), value, input.readRawLittleEndian32());
+ assertTrue(inputType.name(), input.isAtEnd());
+ }
+ }
+ }
+
+ /**
+ * Parses the given bytes using readRawLittleEndian64() and checks that the result matches the
+ * given value.
+ */
+ private void assertReadLittleEndian64(byte[] data, long value) throws Exception {
+ for (InputType inputType : InputType.values()) {
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ CodedInputStream input = inputType.newDecoder(data, blockSize);
+ assertEquals(inputType.name(), value, input.readRawLittleEndian64());
+ assertTrue(inputType.name(), input.isAtEnd());
+ }
+ }
+ }
+
+ /** Tests readRawLittleEndian32() and readRawLittleEndian64(). */
+ public void testReadLittleEndian() throws Exception {
+ assertReadLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertReadLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertReadLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L);
+ assertReadLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L);
+ }
+
+ /** Test decodeZigZag32() and decodeZigZag64(). */
+ public void testDecodeZigZag() throws Exception {
+ assertEquals(0, CodedInputStream.decodeZigZag32(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag32(1));
+ assertEquals(1, CodedInputStream.decodeZigZag32(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag32(3));
+ assertEquals(0x3FFFFFFF, CodedInputStream.decodeZigZag32(0x7FFFFFFE));
+ assertEquals(0xC0000000, CodedInputStream.decodeZigZag32(0x7FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedInputStream.decodeZigZag32(0xFFFFFFFE));
+ assertEquals(0x80000000, CodedInputStream.decodeZigZag32(0xFFFFFFFF));
+
+ assertEquals(0, CodedInputStream.decodeZigZag64(0));
+ assertEquals(-1, CodedInputStream.decodeZigZag64(1));
+ assertEquals(1, CodedInputStream.decodeZigZag64(2));
+ assertEquals(-2, CodedInputStream.decodeZigZag64(3));
+ assertEquals(0x000000003FFFFFFFL, CodedInputStream.decodeZigZag64(0x000000007FFFFFFEL));
+ assertEquals(0xFFFFFFFFC0000000L, CodedInputStream.decodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL, CodedInputStream.decodeZigZag64(0x00000000FFFFFFFEL));
+ assertEquals(0xFFFFFFFF80000000L, CodedInputStream.decodeZigZag64(0x00000000FFFFFFFFL));
+ assertEquals(0x7FFFFFFFFFFFFFFFL, CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+ assertEquals(0x8000000000000000L, CodedInputStream.decodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+ }
+
+ /** Tests reading and parsing a whole message with every field type. */
+ public void testReadWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ byte[] rawBytes = message.toByteArray();
+ assertEquals(rawBytes.length, message.getSerializedSize());
+
+ for (InputType inputType : InputType.values()) {
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ TestAllTypes message2 = TestAllTypes.parseFrom(inputType.newDecoder(rawBytes, blockSize));
+ TestUtil.assertAllFieldsSet(message2);
+ }
+ }
+ }
+
+ /** Tests skipField(). */
+ public void testSkipWholeMessage() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+ byte[] rawBytes = message.toByteArray();
+
+ InputType[] inputTypes = InputType.values();
+ CodedInputStream[] inputs = new CodedInputStream[inputTypes.length];
+ for (int i = 0; i < inputs.length; ++i) {
+ inputs[i] = inputTypes[i].newDecoder(rawBytes);
+ }
+ UnknownFieldSet.Builder unknownFields = UnknownFieldSet.newBuilder();
+
+ while (true) {
+ CodedInputStream input1 = inputs[0];
+ int tag = input1.readTag();
+ // Ensure that the rest match.
+ for (int i = 1; i < inputs.length; ++i) {
+ assertEquals(inputTypes[i].name(), tag, inputs[i].readTag());
+ }
+ if (tag == 0) {
+ break;
+ }
+ unknownFields.mergeFieldFrom(tag, input1);
+ // Skip the field for the rest of the inputs.
+ for (int i = 1; i < inputs.length; ++i) {
+ inputs[i].skipField(tag);
+ }
+ }
+ }
+
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips exactly up to a limit, this
+ * should not break things.
+ */
+ public void testSkipRawBytesBug() throws Exception {
+ byte[] rawBytes = new byte[] {1, 2};
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawBytes);
+ int limit = input.pushLimit(1);
+ input.skipRawBytes(1);
+ input.popLimit(limit);
+ assertEquals(inputType.name(), 2, input.readRawByte());
+ }
+ }
+
+ /**
+ * Test that a bug in skipRawBytes() has been fixed: if the skip skips past the end of a buffer
+ * with a limit that has been set past the end of that buffer, this should not break things.
+ */
+ public void testSkipRawBytesPastEndOfBufferWithLimit() throws Exception {
+ byte[] rawBytes = new byte[] {1, 2, 3, 4, 5};
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawBytes);
+ int limit = input.pushLimit(4);
+ // In order to expose the bug we need to read at least one byte to prime the
+ // buffer inside the CodedInputStream.
+ assertEquals(inputType.name(), 1, input.readRawByte());
+ // Skip to the end of the limit.
+ input.skipRawBytes(3);
+ assertTrue(inputType.name(), input.isAtEnd());
+ input.popLimit(limit);
+ assertEquals(inputType.name(), 5, input.readRawByte());
+ }
+ }
+
+ public void testReadHugeBlob() throws Exception {
+ // Allocate and initialize a 1MB blob.
+ byte[] blob = new byte[1 << 20];
+ for (int i = 0; i < blob.length; i++) {
+ blob[i] = (byte) i;
+ }
+
+ // Make a message containing it.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ builder.setOptionalBytes(ByteString.copyFrom(blob));
+ TestAllTypes message = builder.build();
+
+ byte[] data = message.toByteArray();
+ for (InputType inputType : InputType.values()) {
+ // Serialize and parse it. Make sure to parse from an InputStream, not
+ // directly from a ByteString, so that CodedInputStream uses buffered
+ // reading.
+ TestAllTypes message2 = TestAllTypes.parseFrom(inputType.newDecoder(data));
+
+ assertEquals(inputType.name(), message.getOptionalBytes(), message2.getOptionalBytes());
+
+ // Make sure all the other fields were parsed correctly.
+ TestAllTypes message3 =
+ TestAllTypes.newBuilder(message2)
+ .setOptionalBytes(TestUtil.getAllSet().getOptionalBytes())
+ .build();
+ TestUtil.assertAllFieldsSet(message3);
+ }
+ }
+
+ public void testReadMaliciouslyLargeBlob() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(0x7FFFFFFF);
+ output.writeRawBytes(new byte[32]); // Pad with a few random bytes.
+ output.flush();
+
+ byte[] data = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(data);
+ assertEquals(tag, input.readTag());
+ try {
+ input.readBytes();
+ fail(inputType.name() + ": Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+ }
+
+ /**
+ * Test we can do messages that are up to CodedInputStream#DEFAULT_SIZE_LIMIT
+ * in size (2G or Integer#MAX_SIZE).
+ * @throws IOException
+ */
+ public void testParseMessagesCloseTo2G() throws IOException {
+ byte[] serializedMessage = getBigSerializedMessage();
+ // How many of these big messages do we need to take us near our 2G limit?
+ int count = Integer.MAX_VALUE / serializedMessage.length;
+ // Now make an inputstream that will fake a near 2G message of messages
+ // returning our big serialized message 'count' times.
+ InputStream is = new RepeatingInputStream(serializedMessage, count);
+ // Parse should succeed!
+ TestAllTypes.parseFrom(is);
+ }
+
+ /**
+ * Test there is an exception if a message exceeds
+ * CodedInputStream#DEFAULT_SIZE_LIMIT in size (2G or Integer#MAX_SIZE).
+ * @throws IOException
+ */
+ public void testParseMessagesOver2G() throws IOException {
+ byte[] serializedMessage = getBigSerializedMessage();
+ // How many of these big messages do we need to take us near our 2G limit?
+ int count = Integer.MAX_VALUE / serializedMessage.length;
+ // Now add one to take us over the limit
+ count++;
+ // Now make an inputstream that will fake a near 2G message of messages
+ // returning our big serialized message 'count' times.
+ InputStream is = new RepeatingInputStream(serializedMessage, count);
+ try {
+ TestAllTypes.parseFrom(is);
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ assertTrue(e.getMessage().contains("too large"));
+ }
+ }
+
+ /*
+ * @return A serialized big message.
+ */
+ private static byte[] getBigSerializedMessage() {
+ byte[] value = new byte[16 * 1024 * 1024];
+ ByteString bsValue = ByteString.wrap(value);
+ return TestAllTypes.newBuilder().setOptionalBytes(bsValue).build().toByteArray();
+ }
+
+ /*
+ * An input stream that repeats a byte arrays' content a number of times.
+ * Simulates really large input without consuming loads of memory. Used above
+ * to test the parsing behavior when the input size exceeds 2G or close to it.
+ */
+ private static class RepeatingInputStream extends InputStream {
+ private final byte[] serializedMessage;
+ private final int count;
+ private int index = 0;
+ private int offset = 0;
+
+ RepeatingInputStream(byte[] serializedMessage, int count) {
+ this.serializedMessage = serializedMessage;
+ this.count = count;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (this.offset == this.serializedMessage.length) {
+ this.index++;
+ this.offset = 0;
+ }
+ if (this.index == this.count) {
+ return -1;
+ }
+ return this.serializedMessage[offset++];
+ }
+ }
+
+ private TestRecursiveMessage makeRecursiveMessage(int depth) {
+ if (depth == 0) {
+ return TestRecursiveMessage.newBuilder().setI(5).build();
+ } else {
+ return TestRecursiveMessage.newBuilder().setA(makeRecursiveMessage(depth - 1)).build();
+ }
+ }
+
+ private void assertMessageDepth(String msg, TestRecursiveMessage message, int depth) {
+ if (depth == 0) {
+ assertFalse(msg, message.hasA());
+ assertEquals(msg, 5, message.getI());
+ } else {
+ assertTrue(msg, message.hasA());
+ assertMessageDepth(msg, message.getA(), depth - 1);
+ }
+ }
+
+ public void testMaliciousRecursion() throws Exception {
+ byte[] data100 = makeRecursiveMessage(100).toByteArray();
+ byte[] data101 = makeRecursiveMessage(101).toByteArray();
+
+ for (InputType inputType : InputType.values()) {
+ assertMessageDepth(
+ inputType.name(), TestRecursiveMessage.parseFrom(inputType.newDecoder(data100)), 100);
+
+ try {
+ TestRecursiveMessage.parseFrom(inputType.newDecoder(data101));
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+
+ CodedInputStream input = inputType.newDecoder(data100);
+ input.setRecursionLimit(8);
+ try {
+ TestRecursiveMessage.parseFrom(input);
+ fail(inputType.name() + ": Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException e) {
+ // success.
+ }
+ }
+ }
+
+ private void checkSizeLimitExceeded(InvalidProtocolBufferException e) {
+ assertEquals(InvalidProtocolBufferException.sizeLimitExceeded().getMessage(), e.getMessage());
+ }
+
+ public void testSizeLimit() throws Exception {
+ // NOTE: Size limit only applies to the stream-backed CIS.
+ CodedInputStream input =
+ CodedInputStream.newInstance(
+ new SmallBlockInputStream(TestUtil.getAllSet().toByteArray(), 16));
+ input.setSizeLimit(16);
+
+ try {
+ TestAllTypes.parseFrom(input);
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+ }
+
+ public void testResetSizeCounter() throws Exception {
+ // NOTE: Size limit only applies to the stream-backed CIS.
+ CodedInputStream input =
+ CodedInputStream.newInstance(new SmallBlockInputStream(new byte[256], 8));
+ input.setSizeLimit(16);
+ input.readRawBytes(16);
+ assertEquals(16, input.getTotalBytesRead());
+
+ try {
+ input.readRawByte();
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ input.readRawByte(); // No exception thrown.
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ input.readRawBytes(16);
+ assertEquals(16, input.getTotalBytesRead());
+ input.resetSizeCounter();
+
+ try {
+ input.readRawBytes(17); // Hits limit again.
+ fail("Should have thrown an exception!");
+ } catch (InvalidProtocolBufferException expected) {
+ checkSizeLimitExceeded(expected);
+ }
+ }
+
+ public void testSizeLimitMultipleMessages() throws Exception {
+ // NOTE: Size limit only applies to the stream-backed CIS.
+ byte[] bytes = new byte[256];
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[i] = (byte) i;
+ }
+ CodedInputStream input = CodedInputStream.newInstance(new SmallBlockInputStream(bytes, 7));
+ input.setSizeLimit(16);
+ for (int i = 0; i < 256 / 16; i++) {
+ byte[] message = input.readRawBytes(16);
+ for (int j = 0; j < message.length; j++) {
+ assertEquals(i * 16 + j, message[j] & 0xff);
+ }
+ assertEquals(16, input.getTotalBytesRead());
+ input.resetSizeCounter();
+ assertEquals(0, input.getTotalBytesRead());
+ }
+ }
+
+ public void testReadString() throws Exception {
+ String lorem = "Lorem ipsum dolor sit amet ";
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 4096; i += lorem.length()) {
+ builder.append(lorem);
+ }
+ lorem = builder.toString().substring(0, 4096);
+ byte[] bytes = lorem.getBytes("UTF-8");
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(bytes.length);
+ output.writeRawBytes(bytes);
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawInput);
+ assertEquals(inputType.name(), tag, input.readTag());
+ String text = input.readString();
+ assertEquals(inputType.name(), lorem, text);
+ }
+ }
+
+ public void testReadStringRequireUtf8() throws Exception {
+ String lorem = "Lorem ipsum dolor sit amet ";
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 4096; i += lorem.length()) {
+ builder.append(lorem);
+ }
+ lorem = builder.toString().substring(0, 4096);
+ byte[] bytes = lorem.getBytes("UTF-8");
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(bytes.length);
+ output.writeRawBytes(bytes);
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawInput);
+ assertEquals(inputType.name(), tag, input.readTag());
+ String text = input.readStringRequireUtf8();
+ assertEquals(inputType.name(), lorem, text);
+ }
+ }
+
+ /**
+ * Tests that if we readString invalid UTF-8 bytes, no exception is thrown. Instead, the invalid
+ * bytes are replaced with the Unicode "replacement character" U+FFFD.
+ */
+ public void testReadStringInvalidUtf8() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 0x80});
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawInput);
+ assertEquals(inputType.name(), tag, input.readTag());
+ String text = input.readString();
+ assertEquals(inputType.name(), 0xfffd, text.charAt(0));
+ }
+ }
+
+ /**
+ * Tests that if we readStringRequireUtf8 invalid UTF-8 bytes, an InvalidProtocolBufferException
+ * is thrown.
+ */
+ public void testReadStringRequireUtf8InvalidUtf8() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+
+ int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ output.writeRawVarint32(tag);
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 0x80});
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream input = inputType.newDecoder(rawInput);
+ assertEquals(tag, input.readTag());
+ try {
+ input.readStringRequireUtf8();
+ fail(inputType.name() + ": Expected invalid UTF-8 exception.");
+ } catch (InvalidProtocolBufferException exception) {
+ assertEquals(
+ inputType.name(), "Protocol message had invalid UTF-8.", exception.getMessage());
+ }
+ }
+ }
+
+ public void testReadFromSlice() throws Exception {
+ byte[] bytes = bytes(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ CodedInputStream in = CodedInputStream.newInstance(bytes, 3, 5);
+ assertEquals(0, in.getTotalBytesRead());
+ for (int i = 3; i < 8; i++) {
+ assertEquals(i, in.readRawByte());
+ assertEquals(i - 2, in.getTotalBytesRead());
+ }
+ // eof
+ assertEquals(0, in.readTag());
+ assertEquals(5, in.getTotalBytesRead());
+ }
+
+ public void testInvalidTag() throws Exception {
+ // Any tag number which corresponds to field number zero is invalid and
+ // should throw InvalidProtocolBufferException.
+ for (InputType inputType : InputType.values()) {
+ for (int i = 0; i < 8; i++) {
+ try {
+ inputType.newDecoder(bytes(i)).readTag();
+ fail(inputType.name() + ": Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(
+ inputType.name(),
+ InvalidProtocolBufferException.invalidTag().getMessage(),
+ e.getMessage());
+ }
+ }
+ }
+ }
+
+ public void testReadByteArray() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 23});
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 45});
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream inputStream = inputType.newDecoder(rawInput);
+
+ byte[] result = inputStream.readByteArray();
+ assertEquals(inputType.name(), 0, result.length);
+ result = inputStream.readByteArray();
+ assertEquals(inputType.name(), 1, result.length);
+ assertEquals(inputType.name(), (byte) 23, result[0]);
+ result = inputStream.readByteArray();
+ assertEquals(inputType.name(), 1, result.length);
+ assertEquals(inputType.name(), (byte) 45, result[0]);
+ result = inputStream.readByteArray();
+ assertEquals(inputType.name(), bytesLength, result.length);
+ assertEquals(inputType.name(), (byte) 67, result[0]);
+ assertEquals(inputType.name(), (byte) 89, result[bytesLength - 1]);
+ }
+ }
+
+ public void testReadByteBuffer() throws Exception {
+ ByteString.Output rawOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 23});
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 45});
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+
+ output.flush();
+
+ byte[] rawInput = rawOutput.toByteString().toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream inputStream = inputType.newDecoder(rawInput);
+
+ ByteBuffer result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), 0, result.capacity());
+ result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), bytesLength, result.capacity());
+ assertEquals(inputType.name(), (byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals(inputType.name(), (byte) 89, result.get());
+ }
+ }
+
+ public void testReadByteBufferAliasing() throws Exception {
+ ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream);
+ // Zero-sized bytes field.
+ output.writeRawVarint32(0);
+ // One one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 23});
+ // Another one-byte bytes field
+ output.writeRawVarint32(1);
+ output.writeRawBytes(new byte[] {(byte) 45});
+ // A bytes field large enough that won't fit into the 4K buffer.
+ final int bytesLength = 16 * 1024;
+ byte[] bytes = new byte[bytesLength];
+ bytes[0] = (byte) 67;
+ bytes[bytesLength - 1] = (byte) 89;
+ output.writeRawVarint32(bytesLength);
+ output.writeRawBytes(bytes);
+ output.flush();
+
+ byte[] data = byteArrayStream.toByteArray();
+
+ for (InputType inputType : InputType.values()) {
+ if (inputType == InputType.STREAM) {
+ // Aliasing doesn't apply to stream-backed CIS.
+ continue;
+ }
+
+ // Without aliasing
+ CodedInputStream inputStream = inputType.newDecoder(data);
+ ByteBuffer result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), 0, result.capacity());
+ result = inputStream.readByteBuffer();
+ assertTrue(inputType.name(), result.array() != data);
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(inputType.name(), result.array() != data);
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ assertTrue(inputType.name(), result.array() != data);
+ assertEquals(inputType.name(), bytesLength, result.capacity());
+ assertEquals(inputType.name(), (byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals(inputType.name(), (byte) 89, result.get());
+
+ // Enable aliasing
+ inputStream = inputType.newDecoder(data);
+ inputStream.enableAliasing(true);
+ result = inputStream.readByteBuffer();
+ assertEquals(inputType.name(), 0, result.capacity());
+ result = inputStream.readByteBuffer();
+ if (result.hasArray()) {
+ assertTrue(inputType.name(), result.array() == data);
+ }
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 23, result.get());
+ result = inputStream.readByteBuffer();
+ if (result.hasArray()) {
+ assertTrue(inputType.name(), result.array() == data);
+ }
+ assertEquals(inputType.name(), 1, result.capacity());
+ assertEquals(inputType.name(), (byte) 45, result.get());
+ result = inputStream.readByteBuffer();
+ if (result.hasArray()) {
+ assertTrue(inputType.name(), result.array() == data);
+ }
+ assertEquals(inputType.name(), bytesLength, result.capacity());
+ assertEquals(inputType.name(), (byte) 67, result.get());
+ result.position(bytesLength - 1);
+ assertEquals(inputType.name(), (byte) 89, result.get());
+ }
+ }
+
+ public void testCompatibleTypes() throws Exception {
+ long data = 0x100000000L;
+ Int64Message message = Int64Message.newBuilder().setData(data).build();
+ byte[] serialized = message.toByteArray();
+ for (InputType inputType : InputType.values()) {
+ CodedInputStream inputStream = inputType.newDecoder(serialized);
+
+ // Test int64(long) is compatible with bool(boolean)
+ BoolMessage msg2 = BoolMessage.parseFrom(inputStream);
+ assertTrue(msg2.getData());
+
+ // Test int64(long) is compatible with int32(int)
+ inputStream = inputType.newDecoder(serialized);
+ Int32Message msg3 = Int32Message.parseFrom(inputStream);
+ assertEquals((int) data, msg3.getData());
+ }
+ }
+
+ public void testSkipInvalidVarint_FastPath() throws Exception {
+ // Fast path: We have >= 10 bytes available. Ensure we properly recognize a non-ending varint.
+ byte[] data = new byte[] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0};
+ for (InputType inputType : InputType.values()) {
+ try {
+ CodedInputStream input = inputType.newDecoder(data);
+ input.skipField(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT));
+ fail(inputType.name() + ": Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected
+ }
+ }
+ }
+
+ public void testSkipInvalidVarint_SlowPath() throws Exception {
+ // Slow path: < 10 bytes available. Ensure we properly recognize a non-ending varint.
+ byte[] data = new byte[] {-1, -1, -1, -1, -1, -1, -1, -1, -1};
+ for (InputType inputType : InputType.values()) {
+ try {
+ CodedInputStream input = inputType.newDecoder(data);
+ input.skipField(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT));
+ fail(inputType.name() + ": Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
new file mode 100644
index 0000000000..78f415c254
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java
@@ -0,0 +1,795 @@
+// 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 com.google.protobuf.CodedOutputStream.OutOfSpaceException;
+import protobuf_unittest.UnittestProto.SparseEnumMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestSparseEnum;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link CodedOutputStream}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class CodedOutputStreamTest extends TestCase {
+ private interface Coder {
+ CodedOutputStream stream();
+
+ byte[] toByteArray();
+
+ OutputType getOutputType();
+ }
+
+ private static final class OutputStreamCoder implements Coder {
+ private final CodedOutputStream stream;
+ private final ByteArrayOutputStream output;
+
+ OutputStreamCoder(int size) {
+ output = new ByteArrayOutputStream();
+ stream = CodedOutputStream.newInstance(output, size);
+ }
+
+ @Override
+ public CodedOutputStream stream() {
+ return stream;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return output.toByteArray();
+ }
+
+ @Override
+ public OutputType getOutputType() {
+ return OutputType.STREAM;
+ }
+ }
+
+ private static final class ArrayCoder implements Coder {
+ private final CodedOutputStream stream;
+ private final byte[] bytes;
+
+ ArrayCoder(int size) {
+ bytes = new byte[size];
+ stream = CodedOutputStream.newInstance(bytes);
+ }
+
+ @Override
+ public CodedOutputStream stream() {
+ return stream;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ return Arrays.copyOf(bytes, stream.getTotalBytesWritten());
+ }
+
+ @Override
+ public OutputType getOutputType() {
+ return OutputType.ARRAY;
+ }
+ }
+
+ private static final class NioHeapCoder implements Coder {
+ private final CodedOutputStream stream;
+ private final ByteBuffer buffer;
+ private final int initialPosition;
+
+ NioHeapCoder(int size) {
+ this(size, 0);
+ }
+
+ NioHeapCoder(int size, int initialPosition) {
+ this.initialPosition = initialPosition;
+ buffer = ByteBuffer.allocate(size);
+ buffer.position(initialPosition);
+ stream = CodedOutputStream.newInstance(buffer);
+ }
+
+ @Override
+ public CodedOutputStream stream() {
+ return stream;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ ByteBuffer dup = buffer.duplicate();
+ dup.position(initialPosition);
+ dup.limit(buffer.position());
+
+ byte[] bytes = new byte[dup.remaining()];
+ dup.get(bytes);
+ return bytes;
+ }
+
+ @Override
+ public OutputType getOutputType() {
+ return OutputType.NIO_HEAP;
+ }
+ }
+
+ private static final class NioDirectCoder implements Coder {
+ private final int initialPosition;
+ private final CodedOutputStream stream;
+ private final ByteBuffer buffer;
+ private final boolean unsafe;
+
+ NioDirectCoder(int size, boolean unsafe) {
+ this(size, 0, unsafe);
+ }
+
+ NioDirectCoder(int size, int initialPosition, boolean unsafe) {
+ this.unsafe = unsafe;
+ this.initialPosition = initialPosition;
+ buffer = ByteBuffer.allocateDirect(size);
+ buffer.position(initialPosition);
+ stream =
+ unsafe
+ ? CodedOutputStream.newUnsafeInstance(buffer)
+ : CodedOutputStream.newSafeInstance(buffer);
+ }
+
+ @Override
+ public CodedOutputStream stream() {
+ return stream;
+ }
+
+ @Override
+ public byte[] toByteArray() {
+ ByteBuffer dup = buffer.duplicate();
+ dup.position(initialPosition);
+ dup.limit(buffer.position());
+
+ byte[] bytes = new byte[dup.remaining()];
+ dup.get(bytes);
+ return bytes;
+ }
+
+ @Override
+ public OutputType getOutputType() {
+ return unsafe ? OutputType.NIO_DIRECT_SAFE : OutputType.NIO_DIRECT_UNSAFE;
+ }
+ }
+
+ private enum OutputType {
+ ARRAY() {
+ @Override
+ Coder newCoder(int size) {
+ return new ArrayCoder(size);
+ }
+ },
+ NIO_HEAP() {
+ @Override
+ Coder newCoder(int size) {
+ return new NioHeapCoder(size);
+ }
+ },
+ NIO_DIRECT_SAFE() {
+ @Override
+ Coder newCoder(int size) {
+ return new NioDirectCoder(size, false);
+ }
+ },
+ NIO_DIRECT_UNSAFE() {
+ @Override
+ Coder newCoder(int size) {
+ return new NioDirectCoder(size, true);
+ }
+ },
+ STREAM() {
+ @Override
+ Coder newCoder(int size) {
+ return new OutputStreamCoder(size);
+ }
+ };
+
+ abstract Coder newCoder(int size);
+ }
+
+ /** Checks that invariants are maintained for varint round trip input and output. */
+ public void testVarintRoundTrips() throws Exception {
+ for (OutputType outputType : OutputType.values()) {
+ assertVarintRoundTrip(outputType, 0L);
+ for (int bits = 0; bits < 64; bits++) {
+ long value = 1L << bits;
+ assertVarintRoundTrip(outputType, value);
+ assertVarintRoundTrip(outputType, value + 1);
+ assertVarintRoundTrip(outputType, value - 1);
+ assertVarintRoundTrip(outputType, -value);
+ }
+ }
+ }
+
+ /** Tests writeRawVarint32() and writeRawVarint64(). */
+ public void testWriteVarint() throws Exception {
+ assertWriteVarint(bytes(0x00), 0);
+ assertWriteVarint(bytes(0x01), 1);
+ assertWriteVarint(bytes(0x7f), 127);
+ // 14882
+ assertWriteVarint(bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
+ // 2961488830
+ assertWriteVarint(
+ bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bL << 28));
+
+ // 64-bit
+ // 7256456126
+ assertWriteVarint(
+ bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
+ (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bL << 28));
+ // 41256202580718336
+ assertWriteVarint(
+ bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
+ (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43L << 28) | (0x49L << 35)
+ | (0x24L << 42) | (0x49L << 49));
+ // 11964378330978735131
+ assertWriteVarint(
+ bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
+ (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bL << 28) | (0x56L << 35)
+ | (0x00L << 42) | (0x05L << 49) | (0x26L << 56) | (0x01L << 63));
+ }
+
+ /** Tests writeRawLittleEndian32() and writeRawLittleEndian64(). */
+ public void testWriteLittleEndian() throws Exception {
+ assertWriteLittleEndian32(bytes(0x78, 0x56, 0x34, 0x12), 0x12345678);
+ assertWriteLittleEndian32(bytes(0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef0);
+
+ assertWriteLittleEndian64(
+ bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12), 0x123456789abcdef0L);
+ assertWriteLittleEndian64(
+ bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a), 0x9abcdef012345678L);
+ }
+
+ /** Test encodeZigZag32() and encodeZigZag64(). */
+ public void testEncodeZigZag() throws Exception {
+ assertEquals(0, CodedOutputStream.encodeZigZag32(0));
+ assertEquals(1, CodedOutputStream.encodeZigZag32(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag32(1));
+ assertEquals(3, CodedOutputStream.encodeZigZag32(-2));
+ assertEquals(0x7FFFFFFE, CodedOutputStream.encodeZigZag32(0x3FFFFFFF));
+ assertEquals(0x7FFFFFFF, CodedOutputStream.encodeZigZag32(0xC0000000));
+ assertEquals(0xFFFFFFFE, CodedOutputStream.encodeZigZag32(0x7FFFFFFF));
+ assertEquals(0xFFFFFFFF, CodedOutputStream.encodeZigZag32(0x80000000));
+
+ assertEquals(0, CodedOutputStream.encodeZigZag64(0));
+ assertEquals(1, CodedOutputStream.encodeZigZag64(-1));
+ assertEquals(2, CodedOutputStream.encodeZigZag64(1));
+ assertEquals(3, CodedOutputStream.encodeZigZag64(-2));
+ assertEquals(0x000000007FFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000003FFFFFFFL));
+ assertEquals(0x000000007FFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFFC0000000L));
+ assertEquals(0x00000000FFFFFFFEL, CodedOutputStream.encodeZigZag64(0x000000007FFFFFFFL));
+ assertEquals(0x00000000FFFFFFFFL, CodedOutputStream.encodeZigZag64(0xFFFFFFFF80000000L));
+ assertEquals(0xFFFFFFFFFFFFFFFEL, CodedOutputStream.encodeZigZag64(0x7FFFFFFFFFFFFFFFL));
+ assertEquals(0xFFFFFFFFFFFFFFFFL, CodedOutputStream.encodeZigZag64(0x8000000000000000L));
+
+ // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
+ // were chosen semi-randomly via keyboard bashing.
+ assertEquals(0, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(0)));
+ assertEquals(1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(1)));
+ assertEquals(-1, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-1)));
+ assertEquals(14927, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(14927)));
+ assertEquals(-3612, CodedOutputStream.encodeZigZag32(CodedInputStream.decodeZigZag32(-3612)));
+
+ assertEquals(0, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(0)));
+ assertEquals(1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(1)));
+ assertEquals(-1, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-1)));
+ assertEquals(14927, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(14927)));
+ assertEquals(-3612, CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-3612)));
+
+ assertEquals(
+ 856912304801416L,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(856912304801416L)));
+ assertEquals(
+ -75123905439571256L,
+ CodedOutputStream.encodeZigZag64(CodedInputStream.decodeZigZag64(-75123905439571256L)));
+ }
+
+ /** Tests writing a whole message with every field type. */
+ public void testWriteWholeMessage() throws Exception {
+ final byte[] expectedBytes = TestUtil.getGoldenMessage().toByteArray();
+ TestAllTypes message = TestUtil.getAllSet();
+
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(message.getSerializedSize());
+ message.writeTo(coder.stream());
+ coder.stream().flush();
+ byte[] rawBytes = coder.toByteArray();
+ assertEqualBytes(outputType, expectedBytes, rawBytes);
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ Coder coder = OutputType.STREAM.newCoder(blockSize);
+ message.writeTo(coder.stream());
+ coder.stream().flush();
+ assertEqualBytes(OutputType.STREAM, expectedBytes, coder.toByteArray());
+ }
+ }
+
+ /**
+ * Tests writing a whole message with every packed field type. Ensures the
+ * wire format of packed fields is compatible with C++.
+ */
+ public void testWriteWholePackedFieldsMessage() throws Exception {
+ byte[] expectedBytes = TestUtil.getGoldenPackedFieldsMessage().toByteArray();
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(message.getSerializedSize());
+ message.writeTo(coder.stream());
+ coder.stream().flush();
+ byte[] rawBytes = coder.toByteArray();
+ assertEqualBytes(outputType, expectedBytes, rawBytes);
+ }
+ }
+
+ /**
+ * Test writing a message containing a negative enum value. This used to
+ * fail because the size was not properly computed as a sign-extended varint.
+ */
+ public void testWriteMessageWithNegativeEnumValue() throws Exception {
+ SparseEnumMessage message =
+ SparseEnumMessage.newBuilder().setSparseEnum(TestSparseEnum.SPARSE_E).build();
+ assertTrue(message.getSparseEnum().getNumber() < 0);
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(message.getSerializedSize());
+ message.writeTo(coder.stream());
+ coder.stream().flush();
+ byte[] rawBytes = coder.toByteArray();
+ SparseEnumMessage message2 = SparseEnumMessage.parseFrom(rawBytes);
+ assertEquals(TestSparseEnum.SPARSE_E, message2.getSparseEnum());
+ }
+ }
+
+ /** Test getTotalBytesWritten() */
+ public void testGetTotalBytesWritten() throws Exception {
+ Coder coder = OutputType.STREAM.newCoder(4 * 1024);
+
+ // Write some some bytes (more than the buffer can hold) and verify that totalWritten
+ // is correct.
+ byte[] value = "abcde".getBytes(Internal.UTF_8);
+ for (int i = 0; i < 1024; ++i) {
+ coder.stream().writeRawBytes(value, 0, value.length);
+ }
+ assertEquals(value.length * 1024, coder.stream().getTotalBytesWritten());
+
+ // Now write an encoded string.
+ String string =
+ "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ // Ensure we take the slower fast path.
+ assertTrue(CodedOutputStream.computeUInt32SizeNoTag(string.length())
+ != CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+
+ coder.stream().writeStringNoTag(string);
+ coder.stream().flush();
+ int stringSize = CodedOutputStream.computeStringSizeNoTag(string);
+
+ // Verify that the total bytes written is correct
+ assertEquals((value.length * 1024) + stringSize, coder.stream().getTotalBytesWritten());
+ }
+
+ // TODO(dweis): Write a comprehensive test suite for CodedOutputStream that covers more than just
+ // this case.
+ public void testWriteStringNoTag_fastpath() throws Exception {
+ int bufferSize = 153;
+ String threeBytesPer = "\u0981";
+ String string = threeBytesPer;
+ for (int i = 0; i < 50; i++) {
+ string += threeBytesPer;
+ }
+ // These checks ensure we will tickle the slower fast path.
+ assertEquals(1, CodedOutputStream.computeUInt32SizeNoTag(string.length()));
+ assertEquals(
+ 2, CodedOutputStream.computeUInt32SizeNoTag(string.length() * Utf8.MAX_BYTES_PER_CHAR));
+ assertEquals(bufferSize, string.length() * Utf8.MAX_BYTES_PER_CHAR);
+
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(bufferSize + 2);
+ coder.stream().writeStringNoTag(string);
+ coder.stream().flush();
+ }
+ }
+
+ public void testWriteToByteBuffer() throws Exception {
+ final int bufferSize = 16 * 1024;
+ ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(buffer);
+ // Write raw bytes into the ByteBuffer.
+ final int length1 = 5000;
+ for (int i = 0; i < length1; i++) {
+ codedStream.writeRawByte((byte) 1);
+ }
+ final int length2 = 8 * 1024;
+ byte[] data = new byte[length2];
+ for (int i = 0; i < length2; i++) {
+ data[i] = (byte) 2;
+ }
+ codedStream.writeRawBytes(data);
+ final int length3 = bufferSize - length1 - length2;
+ for (int i = 0; i < length3; i++) {
+ codedStream.writeRawByte((byte) 3);
+ }
+ codedStream.flush();
+
+ // Check that data is correctly written to the ByteBuffer.
+ assertEquals(0, buffer.remaining());
+ buffer.flip();
+ for (int i = 0; i < length1; i++) {
+ assertEquals((byte) 1, buffer.get());
+ }
+ for (int i = 0; i < length2; i++) {
+ assertEquals((byte) 2, buffer.get());
+ }
+ for (int i = 0; i < length3; i++) {
+ assertEquals((byte) 3, buffer.get());
+ }
+ }
+
+ public void testWriteByteBuffer() throws Exception {
+ byte[] value = "abcde".getBytes(Internal.UTF_8);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedStream = CodedOutputStream.newInstance(outputStream);
+ ByteBuffer byteBuffer = ByteBuffer.wrap(value, 0, 1);
+ // This will actually write 5 bytes into the CodedOutputStream as the
+ // ByteBuffer's capacity() is 5.
+ codedStream.writeRawBytes(byteBuffer);
+ // The above call shouldn't affect the ByteBuffer's state.
+ assertEquals(0, byteBuffer.position());
+ assertEquals(1, byteBuffer.limit());
+
+ // The correct way to write part of an array using ByteBuffer.
+ codedStream.writeRawBytes(ByteBuffer.wrap(value, 2, 1).slice());
+
+ codedStream.flush();
+ byte[] result = outputStream.toByteArray();
+ assertEquals(6, result.length);
+ for (int i = 0; i < 5; i++) {
+ assertEquals(value[i], result[i]);
+ }
+ assertEquals(value[2], result[5]);
+ }
+
+ public void testWriteByteArrayWithOffsets() throws Exception {
+ byte[] fullArray = bytes(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);
+ for (OutputType type : new OutputType[] {OutputType.ARRAY}) {
+ Coder coder = type.newCoder(4);
+ coder.stream().writeByteArrayNoTag(fullArray, 2, 2);
+ assertEqualBytes(type, bytes(0x02, 0x33, 0x44), coder.toByteArray());
+ assertEquals(3, coder.stream().getTotalBytesWritten());
+ }
+ }
+
+ public void testSerializeUtf8_MultipleSmallWrites() throws Exception {
+ final String source = "abcdefghijklmnopqrstuvwxyz";
+
+ // Generate the expected output if the source string is written 2 bytes at a time.
+ ByteArrayOutputStream expectedBytesStream = new ByteArrayOutputStream();
+ for (int pos = 0; pos < source.length(); pos += 2) {
+ String substr = source.substring(pos, pos + 2);
+ expectedBytesStream.write(2);
+ expectedBytesStream.write(substr.getBytes(Internal.UTF_8));
+ }
+ final byte[] expectedBytes = expectedBytesStream.toByteArray();
+
+ // For each output type, write the source string 2 bytes at a time and verify the output.
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(expectedBytes.length);
+ for (int pos = 0; pos < source.length(); pos += 2) {
+ String substr = source.substring(pos, pos + 2);
+ coder.stream().writeStringNoTag(substr);
+ }
+ coder.stream().flush();
+ assertEqualBytes(outputType, expectedBytes, coder.toByteArray());
+ }
+ }
+
+ public void testSerializeInvalidUtf8() throws Exception {
+ String[] invalidStrings = new String[] {newString(Character.MIN_HIGH_SURROGATE),
+ "foobar" + newString(Character.MIN_HIGH_SURROGATE), newString(Character.MIN_LOW_SURROGATE),
+ "foobar" + newString(Character.MIN_LOW_SURROGATE),
+ newString(Character.MIN_HIGH_SURROGATE, Character.MIN_HIGH_SURROGATE)};
+
+ CodedOutputStream outputWithStream = CodedOutputStream.newInstance(new ByteArrayOutputStream());
+ CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[10000]);
+ CodedOutputStream outputWithByteBuffer =
+ CodedOutputStream.newInstance(ByteBuffer.allocate(10000));
+ for (String s : invalidStrings) {
+ // TODO(dweis): These should all fail; instead they are corrupting data.
+ CodedOutputStream.computeStringSizeNoTag(s);
+ outputWithStream.writeStringNoTag(s);
+ outputWithArray.writeStringNoTag(s);
+ outputWithByteBuffer.writeStringNoTag(s);
+ }
+ }
+
+ // TODO(nathanmittler): This test can be deleted once we properly throw IOException while
+ // encoding invalid UTF-8 strings.
+ public void testSerializeInvalidUtf8FollowedByOutOfSpace() throws Exception {
+ final int notEnoughBytes = 4;
+ CodedOutputStream outputWithArray = CodedOutputStream.newInstance(new byte[notEnoughBytes]);
+ CodedOutputStream outputWithByteBuffer =
+ CodedOutputStream.newInstance(ByteBuffer.allocate(notEnoughBytes));
+
+ String invalidString = newString(Character.MIN_HIGH_SURROGATE, 'f', 'o', 'o', 'b', 'a', 'r');
+ try {
+ outputWithArray.writeStringNoTag(invalidString);
+ fail("Expected OutOfSpaceException");
+ } catch (OutOfSpaceException e) {
+ assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+ }
+ try {
+ outputWithByteBuffer.writeStringNoTag(invalidString);
+ fail("Expected OutOfSpaceException");
+ } catch (OutOfSpaceException e) {
+ assertTrue(e.getCause() instanceof IndexOutOfBoundsException);
+ }
+ }
+
+ /** Regression test for https://github.com/google/protobuf/issues/292 */
+ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+ String testCase = "Foooooooo";
+ assertEquals(
+ CodedOutputStream.computeUInt32SizeNoTag(testCase.length()),
+ CodedOutputStream.computeUInt32SizeNoTag(testCase.length() * 3));
+ assertEquals(11, CodedOutputStream.computeStringSize(1, testCase));
+ // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+ // An array of size 1 will cause a failure when trying to write the varint.
+ for (OutputType outputType :
+ new OutputType[] {
+ OutputType.ARRAY,
+ OutputType.NIO_HEAP,
+ OutputType.NIO_DIRECT_SAFE,
+ OutputType.NIO_DIRECT_UNSAFE
+ }) {
+ for (int i = 0; i < 11; i++) {
+ Coder coder = outputType.newCoder(i);
+ try {
+ coder.stream().writeString(1, testCase);
+ fail("Should have thrown an out of space exception");
+ } catch (CodedOutputStream.OutOfSpaceException expected) {
+ }
+ }
+ }
+ }
+
+ public void testDifferentStringLengths() throws Exception {
+ // Test string serialization roundtrip using strings of the following lengths,
+ // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+ // char, hence causing the length delimiter varint to sometimes require more
+ // bytes for the Unicode strings than the ASCII string of the same length.
+ int[] lengths = new int[] {
+ 0,
+ 1,
+ (1 << 4) - 1, // 1 byte for ASCII and Unicode
+ (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+ (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+ (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+ (1 << 17) - 1,
+ // 3 bytes for ASCII and Unicode
+ };
+ for (OutputType outputType : OutputType.values()) {
+ for (int i : lengths) {
+ testEncodingOfString(outputType, 'q', i); // 1 byte per char
+ testEncodingOfString(outputType, '\u07FF', i); // 2 bytes per char
+ testEncodingOfString(outputType, '\u0981', i); // 3 bytes per char
+ }
+ }
+ }
+
+ public void testNioEncodersWithInitialOffsets() throws Exception {
+ String value = "abc";
+ for (Coder coder :
+ new Coder[] {
+ new NioHeapCoder(10, 2), new NioDirectCoder(10, 2, false), new NioDirectCoder(10, 2, true)
+ }) {
+ coder.stream().writeStringNoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(coder.getOutputType(), new byte[] {3, 'a', 'b', 'c'}, coder.toByteArray());
+ }
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian32() and checks
+ * that the result matches the given value.
+ */
+ private static void assertWriteLittleEndian32(byte[] data, int value) throws Exception {
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(data.length);
+ coder.stream().writeFixed32NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(outputType, data, coder.toByteArray());
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ Coder coder = OutputType.STREAM.newCoder(blockSize);
+ coder.stream().writeFixed32NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+ }
+ }
+
+ /**
+ * Parses the given bytes using writeRawLittleEndian64() and checks
+ * that the result matches the given value.
+ */
+ private static void assertWriteLittleEndian64(byte[] data, long value) throws Exception {
+ for (OutputType outputType : OutputType.values()) {
+ Coder coder = outputType.newCoder(data.length);
+ coder.stream().writeFixed64NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(outputType, data, coder.toByteArray());
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ Coder coder = OutputType.STREAM.newCoder(blockSize);
+ coder.stream().writeFixed64NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+ }
+ }
+
+ private static String newString(char... chars) {
+ return new String(chars);
+ }
+
+ private static void testEncodingOfString(OutputType outputType, char c, int length)
+ throws Exception {
+ String fullString = fullString(c, length);
+ TestAllTypes testAllTypes = TestAllTypes.newBuilder().setOptionalString(fullString).build();
+ Coder coder = outputType.newCoder(testAllTypes.getSerializedSize());
+ testAllTypes.writeTo(coder.stream());
+ coder.stream().flush();
+ assertEquals(
+ "OuputType: " + outputType,
+ fullString,
+ TestAllTypes.parseFrom(coder.toByteArray()).getOptionalString());
+ }
+
+ private static String fullString(char c, int length) {
+ char[] result = new char[length];
+ Arrays.fill(result, c);
+ return new String(result);
+ }
+
+ /**
+ * Helper to construct a byte array from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private static byte[] bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return bytes;
+ }
+
+ /** Arrays.asList() does not work with arrays of primitives. :( */
+ private static List<Byte> toList(byte[] bytes) {
+ List<Byte> result = new ArrayList<Byte>();
+ for (byte b : bytes) {
+ result.add(b);
+ }
+ return result;
+ }
+
+ private static void assertEqualBytes(OutputType outputType, byte[] a, byte[] b) {
+ assertEquals(outputType.name(), toList(a), toList(b));
+ }
+
+ /**
+ * Writes the given value using writeRawVarint32() and writeRawVarint64() and
+ * checks that the result matches the given bytes.
+ */
+ private static void assertWriteVarint(byte[] data, long value) throws Exception {
+ for (OutputType outputType : OutputType.values()) {
+ // Only test 32-bit write if the value fits into an int.
+ if (value == (int) value) {
+ Coder coder = outputType.newCoder(10);
+ coder.stream().writeUInt32NoTag((int) value);
+ coder.stream().flush();
+ assertEqualBytes(outputType, data, coder.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+ }
+
+ {
+ Coder coder = outputType.newCoder(10);
+ coder.stream().writeUInt64NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(outputType, data, coder.toByteArray());
+
+ // Also try computing size.
+ assertEquals(data.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+ }
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ // Only test 32-bit write if the value fits into an int.
+ if (value == (int) value) {
+ Coder coder = OutputType.STREAM.newCoder(blockSize);
+ coder.stream().writeUInt64NoTag((int) value);
+ coder.stream().flush();
+ assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+
+ ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, blockSize);
+ output.writeUInt32NoTag((int) value);
+ output.flush();
+ assertEqualBytes(OutputType.STREAM, data, rawOutput.toByteArray());
+ }
+
+ {
+ Coder coder = OutputType.STREAM.newCoder(blockSize);
+ coder.stream().writeUInt64NoTag(value);
+ coder.stream().flush();
+ assertEqualBytes(OutputType.STREAM, data, coder.toByteArray());
+ }
+ }
+ }
+
+ private static void assertVarintRoundTrip(OutputType outputType, long value) throws Exception {
+ {
+ Coder coder = outputType.newCoder(10);
+ coder.stream().writeUInt64NoTag(value);
+ coder.stream().flush();
+ byte[] bytes = coder.toByteArray();
+ assertEquals(
+ outputType.name(), bytes.length, CodedOutputStream.computeUInt64SizeNoTag(value));
+ CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+ assertEquals(outputType.name(), value, input.readRawVarint64());
+ }
+
+ if (value == (int) value) {
+ Coder coder = outputType.newCoder(10);
+ coder.stream().writeUInt32NoTag((int) value);
+ coder.stream().flush();
+ byte[] bytes = coder.toByteArray();
+ assertEquals(
+ outputType.name(), bytes.length, CodedOutputStream.computeUInt32SizeNoTag((int) value));
+ CodedInputStream input = CodedInputStream.newInstance(new ByteArrayInputStream(bytes));
+ assertEquals(outputType.name(), value, input.readRawVarint32());
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
new file mode 100644
index 0000000000..2c272a7347
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java
@@ -0,0 +1,79 @@
+// 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 protobuf_unittest.UnittestProto.TestDeprecatedFields;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import junit.framework.TestCase;
+
+/**
+ * Test field deprecation
+ *
+ * @author birdo@google.com (Roberto Scaramuzzi)
+ */
+public class DeprecatedFieldTest extends TestCase {
+ private String[] deprecatedGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32"};
+
+ private String[] deprecatedBuilderGetterNames = {
+ "hasDeprecatedInt32",
+ "getDeprecatedInt32",
+ "clearDeprecatedInt32"};
+
+ private String[] deprecatedBuilderSetterNames = {
+ "setDeprecatedInt32"};
+
+ public void testDeprecatedField() throws Exception {
+ Class<?> deprecatedFields = TestDeprecatedFields.class;
+ Class<?> deprecatedFieldsBuilder = TestDeprecatedFields.Builder.class;
+ for (String name : deprecatedGetterNames) {
+ Method method = deprecatedFields.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderGetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ for (String name : deprecatedBuilderSetterNames) {
+ Method method = deprecatedFieldsBuilder.getMethod(name, int.class);
+ assertTrue("Method " + name + " should be deprecated",
+ isDeprecated(method));
+ }
+ }
+
+ private boolean isDeprecated(AnnotatedElement annotated) {
+ return annotated.isAnnotationPresent(Deprecated.class);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
new file mode 100644
index 0000000000..b60cd62088
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -0,0 +1,819 @@
+// 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 com.google.protobuf.DescriptorProtos.DescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
+import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.DescriptorValidationException;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import com.google.protobuf.Descriptors.ServiceDescriptor;
+import com.google.protobuf.test.UnittestImport;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportEnumForMap;
+import protobuf_unittest.TestCustomOptions;
+import protobuf_unittest.UnittestCustomOptions;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestJsonName;
+import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestReservedFields;
+import protobuf_unittest.UnittestProto.TestService;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link Descriptors}.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DescriptorsTest extends TestCase {
+
+ // Regression test for bug where referencing a FieldDescriptor.Type value
+ // before a FieldDescriptorProto.Type value would yield a
+ // ExceptionInInitializerError.
+ @SuppressWarnings("unused")
+ private static final Object STATIC_INIT_TEST = FieldDescriptor.Type.BOOL;
+
+ public void testFieldTypeEnumMapping() throws Exception {
+ assertEquals(FieldDescriptor.Type.values().length,
+ FieldDescriptorProto.Type.values().length);
+ for (FieldDescriptor.Type type : FieldDescriptor.Type.values()) {
+ FieldDescriptorProto.Type protoType = type.toProto();
+ assertEquals("TYPE_" + type.name(), protoType.name());
+ assertEquals(type, FieldDescriptor.Type.valueOf(protoType));
+ }
+ }
+
+ public void testFileDescriptor() throws Exception {
+ FileDescriptor file = UnittestProto.getDescriptor();
+
+ assertEquals("google/protobuf/unittest.proto", file.getName());
+ assertEquals("protobuf_unittest", file.getPackage());
+
+ assertEquals("UnittestProto", file.getOptions().getJavaOuterClassname());
+ assertEquals("google/protobuf/unittest.proto",
+ file.toProto().getName());
+
+ assertEquals(Arrays.asList(UnittestImport.getDescriptor()),
+ file.getDependencies());
+
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ assertEquals(messageType, file.getMessageTypes().get(0));
+ assertEquals(messageType, file.findMessageTypeByName("TestAllTypes"));
+ assertNull(file.findMessageTypeByName("NoSuchType"));
+ assertNull(file.findMessageTypeByName("protobuf_unittest.TestAllTypes"));
+ for (int i = 0; i < file.getMessageTypes().size(); i++) {
+ assertEquals(i, file.getMessageTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ assertEquals(enumType, file.getEnumTypes().get(0));
+ assertEquals(enumType, file.findEnumTypeByName("ForeignEnum"));
+ assertNull(file.findEnumTypeByName("NoSuchType"));
+ assertNull(file.findEnumTypeByName("protobuf_unittest.ForeignEnum"));
+ assertEquals(Arrays.asList(ImportEnum.getDescriptor(),
+ ImportEnumForMap.getDescriptor()),
+ UnittestImport.getDescriptor().getEnumTypes());
+ for (int i = 0; i < file.getEnumTypes().size(); i++) {
+ assertEquals(i, file.getEnumTypes().get(i).getIndex());
+ }
+
+ ServiceDescriptor service = TestService.getDescriptor();
+ assertEquals(service, file.getServices().get(0));
+ assertEquals(service, file.findServiceByName("TestService"));
+ assertNull(file.findServiceByName("NoSuchType"));
+ assertNull(file.findServiceByName("protobuf_unittest.TestService"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getServices());
+ for (int i = 0; i < file.getServices().size(); i++) {
+ assertEquals(i, file.getServices().get(i).getIndex());
+ }
+
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ assertEquals(extension, file.getExtensions().get(0));
+ assertEquals(extension,
+ file.findExtensionByName("optional_int32_extension"));
+ assertNull(file.findExtensionByName("no_such_ext"));
+ assertNull(file.findExtensionByName(
+ "protobuf_unittest.optional_int32_extension"));
+ assertEquals(Collections.emptyList(),
+ UnittestImport.getDescriptor().getExtensions());
+ for (int i = 0; i < file.getExtensions().size(); i++) {
+ assertEquals(i, file.getExtensions().get(i).getIndex());
+ }
+ }
+
+ public void testDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ Descriptor nestedType = TestAllTypes.NestedMessage.getDescriptor();
+
+ assertEquals("TestAllTypes", messageType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes", messageType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), messageType.getFile());
+ assertNull(messageType.getContainingType());
+ assertEquals(DescriptorProtos.MessageOptions.getDefaultInstance(),
+ messageType.getOptions());
+ assertEquals("TestAllTypes", messageType.toProto().getName());
+
+ assertEquals("NestedMessage", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedMessage",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(messageType, nestedType.getContainingType());
+
+ FieldDescriptor field = messageType.getFields().get(0);
+ assertEquals("optional_int32", field.getName());
+ assertEquals(field, messageType.findFieldByName("optional_int32"));
+ assertNull(messageType.findFieldByName("no_such_field"));
+ assertEquals(field, messageType.findFieldByNumber(1));
+ assertNull(messageType.findFieldByNumber(571283));
+ for (int i = 0; i < messageType.getFields().size(); i++) {
+ assertEquals(i, messageType.getFields().get(i).getIndex());
+ }
+
+ assertEquals(nestedType, messageType.getNestedTypes().get(0));
+ assertEquals(nestedType, messageType.findNestedTypeByName("NestedMessage"));
+ assertNull(messageType.findNestedTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getNestedTypes().size(); i++) {
+ assertEquals(i, messageType.getNestedTypes().get(i).getIndex());
+ }
+
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+ assertEquals(enumType, messageType.getEnumTypes().get(0));
+ assertEquals(enumType, messageType.findEnumTypeByName("NestedEnum"));
+ assertNull(messageType.findEnumTypeByName("NoSuchType"));
+ for (int i = 0; i < messageType.getEnumTypes().size(); i++) {
+ assertEquals(i, messageType.getEnumTypes().get(i).getIndex());
+ }
+ }
+
+ public void testFieldDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ FieldDescriptor primitiveField =
+ messageType.findFieldByName("optional_int32");
+ FieldDescriptor enumField =
+ messageType.findFieldByName("optional_nested_enum");
+ FieldDescriptor messageField =
+ messageType.findFieldByName("optional_foreign_message");
+ FieldDescriptor cordField =
+ messageType.findFieldByName("optional_cord");
+ FieldDescriptor extension =
+ UnittestProto.optionalInt32Extension.getDescriptor();
+ FieldDescriptor nestedExtension = TestRequired.single.getDescriptor();
+
+ assertEquals("optional_int32", primitiveField.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.optional_int32",
+ primitiveField.getFullName());
+ assertEquals(1, primitiveField.getNumber());
+ assertEquals(messageType, primitiveField.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), primitiveField.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, primitiveField.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, primitiveField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ primitiveField.getOptions());
+ assertFalse(primitiveField.isExtension());
+ assertEquals("optional_int32", primitiveField.toProto().getName());
+
+ assertEquals("optional_nested_enum", enumField.getName());
+ assertEquals(FieldDescriptor.Type.ENUM, enumField.getType());
+ assertEquals(FieldDescriptor.JavaType.ENUM, enumField.getJavaType());
+ assertEquals(TestAllTypes.NestedEnum.getDescriptor(),
+ enumField.getEnumType());
+
+ assertEquals("optional_foreign_message", messageField.getName());
+ assertEquals(FieldDescriptor.Type.MESSAGE, messageField.getType());
+ assertEquals(FieldDescriptor.JavaType.MESSAGE, messageField.getJavaType());
+ assertEquals(ForeignMessage.getDescriptor(), messageField.getMessageType());
+
+ assertEquals("optional_cord", cordField.getName());
+ assertEquals(FieldDescriptor.Type.STRING, cordField.getType());
+ assertEquals(FieldDescriptor.JavaType.STRING, cordField.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.CType.CORD,
+ cordField.getOptions().getCtype());
+
+ assertEquals("optional_int32_extension", extension.getName());
+ assertEquals("protobuf_unittest.optional_int32_extension",
+ extension.getFullName());
+ assertEquals(1, extension.getNumber());
+ assertEquals(TestAllExtensions.getDescriptor(),
+ extension.getContainingType());
+ assertEquals(UnittestProto.getDescriptor(), extension.getFile());
+ assertEquals(FieldDescriptor.Type.INT32, extension.getType());
+ assertEquals(FieldDescriptor.JavaType.INT, extension.getJavaType());
+ assertEquals(DescriptorProtos.FieldOptions.getDefaultInstance(),
+ extension.getOptions());
+ assertTrue(extension.isExtension());
+ assertEquals(null, extension.getExtensionScope());
+ assertEquals("optional_int32_extension", extension.toProto().getName());
+
+ assertEquals("single", nestedExtension.getName());
+ assertEquals("protobuf_unittest.TestRequired.single",
+ nestedExtension.getFullName());
+ assertEquals(TestRequired.getDescriptor(),
+ nestedExtension.getExtensionScope());
+ }
+
+ public void testFieldDescriptorLabel() throws Exception {
+ FieldDescriptor requiredField =
+ TestRequired.getDescriptor().findFieldByName("a");
+ FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+ FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+
+ assertTrue(requiredField.isRequired());
+ assertFalse(requiredField.isRepeated());
+ assertFalse(optionalField.isRequired());
+ assertFalse(optionalField.isRepeated());
+ assertFalse(repeatedField.isRequired());
+ assertTrue(repeatedField.isRepeated());
+ }
+
+ public void testFieldDescriptorJsonName() throws Exception {
+ FieldDescriptor requiredField = TestRequired.getDescriptor().findFieldByName("a");
+ FieldDescriptor optionalField = TestAllTypes.getDescriptor().findFieldByName("optional_int32");
+ FieldDescriptor repeatedField = TestAllTypes.getDescriptor().findFieldByName("repeated_int32");
+ assertEquals("a", requiredField.getJsonName());
+ assertEquals("optionalInt32", optionalField.getJsonName());
+ assertEquals("repeatedInt32", repeatedField.getJsonName());
+ }
+
+ public void testFieldDescriptorDefault() throws Exception {
+ Descriptor d = TestAllTypes.getDescriptor();
+ assertFalse(d.findFieldByName("optional_int32").hasDefaultValue());
+ assertEquals(0, d.findFieldByName("optional_int32").getDefaultValue());
+ assertTrue(d.findFieldByName("default_int32").hasDefaultValue());
+ assertEquals(41, d.findFieldByName("default_int32").getDefaultValue());
+
+ d = TestExtremeDefaultValues.getDescriptor();
+ assertEquals(
+ ByteString.copyFrom(
+ "\0\001\007\b\f\n\r\t\013\\\'\"\u00fe".getBytes(Internal.ISO_8859_1)),
+ d.findFieldByName("escaped_bytes").getDefaultValue());
+ assertEquals(-1, d.findFieldByName("large_uint32").getDefaultValue());
+ assertEquals(-1L, d.findFieldByName("large_uint64").getDefaultValue());
+ }
+
+ public void testEnumDescriptor() throws Exception {
+ EnumDescriptor enumType = ForeignEnum.getDescriptor();
+ EnumDescriptor nestedType = TestAllTypes.NestedEnum.getDescriptor();
+
+ assertEquals("ForeignEnum", enumType.getName());
+ assertEquals("protobuf_unittest.ForeignEnum", enumType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), enumType.getFile());
+ assertNull(enumType.getContainingType());
+ assertEquals(DescriptorProtos.EnumOptions.getDefaultInstance(),
+ enumType.getOptions());
+
+ assertEquals("NestedEnum", nestedType.getName());
+ assertEquals("protobuf_unittest.TestAllTypes.NestedEnum",
+ nestedType.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), nestedType.getFile());
+ assertEquals(TestAllTypes.getDescriptor(), nestedType.getContainingType());
+
+ EnumValueDescriptor value = ForeignEnum.FOREIGN_FOO.getValueDescriptor();
+ assertEquals(value, enumType.getValues().get(0));
+ assertEquals("FOREIGN_FOO", value.getName());
+ assertEquals("FOREIGN_FOO", value.toString());
+ assertEquals(4, value.getNumber());
+ assertEquals(value, enumType.findValueByName("FOREIGN_FOO"));
+ assertEquals(value, enumType.findValueByNumber(4));
+ assertNull(enumType.findValueByName("NO_SUCH_VALUE"));
+ for (int i = 0; i < enumType.getValues().size(); i++) {
+ assertEquals(i, enumType.getValues().get(i).getIndex());
+ }
+ }
+
+ public void testServiceDescriptor() throws Exception {
+ ServiceDescriptor service = TestService.getDescriptor();
+
+ assertEquals("TestService", service.getName());
+ assertEquals("protobuf_unittest.TestService", service.getFullName());
+ assertEquals(UnittestProto.getDescriptor(), service.getFile());
+
+
+ MethodDescriptor fooMethod = service.getMethods().get(0);
+ assertEquals("Foo", fooMethod.getName());
+ assertEquals(UnittestProto.FooRequest.getDescriptor(),
+ fooMethod.getInputType());
+ assertEquals(UnittestProto.FooResponse.getDescriptor(),
+ fooMethod.getOutputType());
+ assertEquals(fooMethod, service.findMethodByName("Foo"));
+
+ MethodDescriptor barMethod = service.getMethods().get(1);
+ assertEquals("Bar", barMethod.getName());
+ assertEquals(UnittestProto.BarRequest.getDescriptor(),
+ barMethod.getInputType());
+ assertEquals(UnittestProto.BarResponse.getDescriptor(),
+ barMethod.getOutputType());
+ assertEquals(barMethod, service.findMethodByName("Bar"));
+
+ assertNull(service.findMethodByName("NoSuchMethod"));
+
+ for (int i = 0; i < service.getMethods().size(); i++) {
+ assertEquals(i, service.getMethods().get(i).getIndex());
+ }
+ }
+
+
+ public void testCustomOptions() throws Exception {
+ // Get the descriptor indirectly from a dependent proto class. This is to
+ // ensure that when a proto class is loaded, custom options defined in its
+ // dependencies are also properly initialized.
+ Descriptor descriptor =
+ TestCustomOptions.TestMessageWithCustomOptionsContainer.getDescriptor()
+ .findFieldByName("field").getMessageType();
+
+ assertTrue(
+ descriptor.getOptions().hasExtension(UnittestCustomOptions.messageOpt1));
+ assertEquals(Integer.valueOf(-56),
+ descriptor.getOptions().getExtension(UnittestCustomOptions.messageOpt1));
+
+ FieldDescriptor field = descriptor.findFieldByName("field1");
+ assertNotNull(field);
+
+ assertTrue(
+ field.getOptions().hasExtension(UnittestCustomOptions.fieldOpt1));
+ assertEquals(Long.valueOf(8765432109L),
+ field.getOptions().getExtension(UnittestCustomOptions.fieldOpt1));
+
+ OneofDescriptor oneof = descriptor.getOneofs().get(0);
+ assertNotNull(oneof);
+
+ assertTrue(
+ oneof.getOptions().hasExtension(UnittestCustomOptions.oneofOpt1));
+ assertEquals(Integer.valueOf(-99),
+ oneof.getOptions().getExtension(UnittestCustomOptions.oneofOpt1));
+
+ EnumDescriptor enumType =
+ UnittestCustomOptions.TestMessageWithCustomOptions.AnEnum.getDescriptor();
+
+ assertTrue(
+ enumType.getOptions().hasExtension(UnittestCustomOptions.enumOpt1));
+ assertEquals(Integer.valueOf(-789),
+ enumType.getOptions().getExtension(UnittestCustomOptions.enumOpt1));
+
+ ServiceDescriptor service =
+ UnittestCustomOptions.TestServiceWithCustomOptions.getDescriptor();
+
+ assertTrue(
+ service.getOptions().hasExtension(UnittestCustomOptions.serviceOpt1));
+ assertEquals(Long.valueOf(-9876543210L),
+ service.getOptions().getExtension(UnittestCustomOptions.serviceOpt1));
+
+ MethodDescriptor method = service.findMethodByName("Foo");
+ assertNotNull(method);
+
+ assertTrue(
+ method.getOptions().hasExtension(UnittestCustomOptions.methodOpt1));
+ assertEquals(UnittestCustomOptions.MethodOpt1.METHODOPT1_VAL2,
+ method.getOptions().getExtension(UnittestCustomOptions.methodOpt1));
+ }
+
+ /**
+ * Test that the FieldDescriptor.Type enum is the same as the
+ * WireFormat.FieldType enum.
+ */
+ public void testFieldTypeTablesMatch() throws Exception {
+ FieldDescriptor.Type[] values1 = FieldDescriptor.Type.values();
+ WireFormat.FieldType[] values2 = WireFormat.FieldType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ /**
+ * Test that the FieldDescriptor.JavaType enum is the same as the
+ * WireFormat.JavaType enum.
+ */
+ public void testJavaTypeTablesMatch() throws Exception {
+ FieldDescriptor.JavaType[] values1 = FieldDescriptor.JavaType.values();
+ WireFormat.JavaType[] values2 = WireFormat.JavaType.values();
+
+ assertEquals(values1.length, values2.length);
+
+ for (int i = 0; i < values1.length; i++) {
+ assertEquals(values1[i].toString(), values2[i].toString());
+ }
+ }
+
+ public void testEnormousDescriptor() throws Exception {
+ // The descriptor for this file is larger than 64k, yet it did not cause
+ // a compiler error due to an over-long string literal.
+ assertTrue(
+ UnittestEnormousDescriptor.getDescriptor()
+ .toProto().getSerializedSize() > 65536);
+ }
+
+ /**
+ * Tests that the DescriptorValidationException works as intended.
+ */
+ public void testDescriptorValidatorException() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .setDefaultValue("invalid")
+ .build())
+ .build())
+ .build();
+ try {
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ // Expected; check that the error message contains some useful hints
+ assertTrue(e.getMessage().indexOf("foo") != -1);
+ assertTrue(e.getMessage().indexOf("Foo") != -1);
+ assertTrue(e.getMessage().indexOf("invalid") != -1);
+ assertTrue(e.getCause() instanceof NumberFormatException);
+ assertTrue(e.getCause().getMessage().indexOf("invalid") != -1);
+ }
+ }
+
+ /**
+ * Tests the translate/crosslink for an example where a message field's name
+ * and type name are the same.
+ */
+ public void testDescriptorComplexCrosslink() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setType(FieldDescriptorProto.Type.TYPE_INT32)
+ .setName("foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Bar")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Foo")
+ .setName("Foo")
+ .setNumber(1)
+ .build())
+ .build())
+ .build();
+ // translate and crosslink
+ FileDescriptor file =
+ Descriptors.FileDescriptor.buildFrom(fileDescriptorProto,
+ new FileDescriptor[0]);
+ // verify resulting descriptors
+ assertNotNull(file);
+ List<Descriptor> msglist = file.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 2);
+ boolean barFound = false;
+ for (Descriptor desc : msglist) {
+ if (desc.getName().equals("Bar")) {
+ barFound = true;
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ assertTrue(fieldlist.get(0).getType() == FieldDescriptor.Type.MESSAGE);
+ assertTrue(fieldlist.get(0).getMessageType().getName().equals("Foo"));
+ }
+ }
+ assertTrue(barFound);
+ }
+
+ public void testDependencyOrder() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto").build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addDependency("foo.proto")
+ .build();
+ FileDescriptorProto bazProto = FileDescriptorProto.newBuilder()
+ .setName("baz.proto")
+ .addDependency("foo.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .addPublicDependency(1)
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+
+ // Items in the FileDescriptor array can be in any order.
+ Descriptors.FileDescriptor.buildFrom(bazProto,
+ new FileDescriptor[] {fooFile, barFile});
+ Descriptors.FileDescriptor.buildFrom(bazProto,
+ new FileDescriptor[] {barFile, fooFile});
+ }
+
+ public void testInvalidPublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto").build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("boo.proto")
+ .addDependency("foo.proto")
+ .addPublicDependency(1) // Error, should be 0.
+ .build();
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(fooProto,
+ new FileDescriptor[0]);
+ try {
+ Descriptors.FileDescriptor.buildFrom(barProto,
+ new FileDescriptor[] {fooFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(
+ e.getMessage().indexOf("Invalid public dependency index.") != -1);
+ }
+ }
+
+ public void testUnknownFieldsDenied() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+
+ try {
+ Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0]);
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(e.getMessage().indexOf("Bar") != -1);
+ assertTrue(e.getMessage().indexOf("is not defined") != -1);
+ }
+ }
+
+ public void testUnknownFieldsAllowed() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
+ }
+
+ public void testHiddenDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[] {barFile});
+
+ try {
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ fail("DescriptorValidationException expected");
+ } catch (DescriptorValidationException e) {
+ assertTrue(e.getMessage().indexOf("Bar") != -1);
+ assertTrue(e.getMessage().indexOf("is not defined") != -1);
+ }
+ }
+
+ public void testPublicDependency() throws Exception {
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .addMessageType(DescriptorProto.newBuilder().setName("Bar"))
+ .build();
+ FileDescriptorProto forwardProto = FileDescriptorProto.newBuilder()
+ .setName("forward.proto")
+ .addDependency("bar.proto")
+ .addPublicDependency(0)
+ .build();
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("forward.proto")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Foo")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+ .setTypeName("Bar")
+ .setName("bar")
+ .setNumber(1)))
+ .build();
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[0]);
+ FileDescriptor forwardFile = Descriptors.FileDescriptor.buildFrom(
+ forwardProto, new FileDescriptor[]{barFile});
+ Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[] {forwardFile});
+ }
+
+ /**
+ * Tests the translate/crosslink for an example with a more complex namespace
+ * referencing.
+ */
+ public void testComplexNamespacePublicDependency() throws Exception {
+ FileDescriptorProto fooProto = FileDescriptorProto.newBuilder()
+ .setName("bar.proto")
+ .setPackage("a.b.c.d.bar.shared")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("MyEnum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("BLAH")
+ .setNumber(1)))
+ .build();
+ FileDescriptorProto barProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addDependency("bar.proto")
+ .setPackage("a.b.c.d.foo.shared")
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("MyMessage")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setTypeName("bar.shared.MyEnum")
+ .setName("MyField")
+ .setNumber(1)))
+ .build();
+ // translate and crosslink
+ FileDescriptor fooFile = Descriptors.FileDescriptor.buildFrom(
+ fooProto, new FileDescriptor[0]);
+ FileDescriptor barFile = Descriptors.FileDescriptor.buildFrom(
+ barProto, new FileDescriptor[]{fooFile});
+ // verify resulting descriptors
+ assertNotNull(barFile);
+ List<Descriptor> msglist = barFile.getMessageTypes();
+ assertNotNull(msglist);
+ assertTrue(msglist.size() == 1);
+ Descriptor desc = msglist.get(0);
+ if (desc.getName().equals("MyMessage")) {
+ assertNotNull(desc.getFields());
+ List<FieldDescriptor> fieldlist = desc.getFields();
+ assertNotNull(fieldlist);
+ assertTrue(fieldlist.size() == 1);
+ FieldDescriptor field = fieldlist.get(0);
+ assertTrue(field.getType() == FieldDescriptor.Type.ENUM);
+ assertTrue(field.getEnumType().getName().equals("MyEnum"));
+ assertTrue(field.getEnumType().getFile().getName().equals("bar.proto"));
+ assertTrue(field.getEnumType().getFile().getPackage().equals(
+ "a.b.c.d.bar.shared"));
+ }
+ }
+
+ public void testOneofDescriptor() throws Exception {
+ Descriptor messageType = TestAllTypes.getDescriptor();
+ FieldDescriptor field =
+ messageType.findFieldByName("oneof_nested_message");
+ OneofDescriptor oneofDescriptor = field.getContainingOneof();
+ assertNotNull(oneofDescriptor);
+ assertSame(oneofDescriptor, messageType.getOneofs().get(0));
+ assertEquals("oneof_field", oneofDescriptor.getName());
+
+ assertEquals(4, oneofDescriptor.getFieldCount());
+ assertSame(oneofDescriptor.getField(1), field);
+
+ assertEquals(4, oneofDescriptor.getFields().size());
+ assertEquals(oneofDescriptor.getFields().get(1), field);
+ }
+
+ public void testMessageDescriptorExtensions() throws Exception {
+ assertFalse(TestAllTypes.getDescriptor().isExtendable());
+ assertTrue(TestAllExtensions.getDescriptor().isExtendable());
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtendable());
+
+ assertFalse(TestAllTypes.getDescriptor().isExtensionNumber(3));
+ assertTrue(TestAllExtensions.getDescriptor().isExtensionNumber(3));
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(42));
+ assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(43));
+ assertFalse(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4142));
+ assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143));
+ }
+
+ public void testReservedFields() {
+ Descriptor d = TestReservedFields.getDescriptor();
+ assertTrue(d.isReservedNumber(2));
+ assertFalse(d.isReservedNumber(8));
+ assertTrue(d.isReservedNumber(9));
+ assertTrue(d.isReservedNumber(10));
+ assertTrue(d.isReservedNumber(11));
+ assertFalse(d.isReservedNumber(12));
+ assertFalse(d.isReservedName("foo"));
+ assertTrue(d.isReservedName("bar"));
+ assertTrue(d.isReservedName("baz"));
+ }
+
+ public void testToString() {
+ assertEquals("protobuf_unittest.TestAllTypes.optional_uint64",
+ UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber(
+ UnittestProto.TestAllTypes.OPTIONAL_UINT64_FIELD_NUMBER).toString());
+ }
+
+ public void testPackedEnumField() throws Exception {
+ FileDescriptorProto fileDescriptorProto = FileDescriptorProto.newBuilder()
+ .setName("foo.proto")
+ .addEnumType(EnumDescriptorProto.newBuilder()
+ .setName("Enum")
+ .addValue(EnumValueDescriptorProto.newBuilder()
+ .setName("FOO")
+ .setNumber(1)
+ .build())
+ .build())
+ .addMessageType(DescriptorProto.newBuilder()
+ .setName("Message")
+ .addField(FieldDescriptorProto.newBuilder()
+ .setName("foo")
+ .setTypeName("Enum")
+ .setNumber(1)
+ .setLabel(FieldDescriptorProto.Label.LABEL_REPEATED)
+ .setOptions(DescriptorProtos.FieldOptions.newBuilder()
+ .setPacked(true)
+ .build())
+ .build())
+ .build())
+ .build();
+ Descriptors.FileDescriptor.buildFrom(
+ fileDescriptorProto, new FileDescriptor[0]);
+ }
+
+ public void testFieldJsonName() throws Exception {
+ Descriptor d = TestJsonName.getDescriptor();
+ assertEquals(6, d.getFields().size());
+ assertEquals("fieldName1", d.getFields().get(0).getJsonName());
+ assertEquals("fieldName2", d.getFields().get(1).getJsonName());
+ assertEquals("FieldName3", d.getFields().get(2).getJsonName());
+ assertEquals("FieldName4", d.getFields().get(3).getJsonName());
+ assertEquals("FIELDNAME5", d.getFields().get(4).getJsonName());
+ assertEquals("@type", d.getFields().get(5).getJsonName());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
new file mode 100644
index 0000000000..d894279297
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java
@@ -0,0 +1,461 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link DoubleArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class DoubleArrayListTest extends TestCase {
+
+ private static final DoubleArrayList UNARY_LIST =
+ newImmutableDoubleArrayList(1);
+ private static final DoubleArrayList TERTIARY_LIST =
+ newImmutableDoubleArrayList(1, 2, 3);
+
+ private DoubleArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new DoubleArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(DoubleArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addDouble(3);
+ list.addDouble(4);
+ list.addDouble(5);
+ list.addDouble(7);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1D, 2D, 3D, 4D));
+ Iterator<Double> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, (double) iterator.next());
+ list.set(0, 1D);
+ assertEquals(2D, (double) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0D);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1D, (double) TERTIARY_LIST.get(0));
+ assertEquals(2D, (double) TERTIARY_LIST.get(1));
+ assertEquals(3D, (double) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetDouble() {
+ assertEquals(1D, TERTIARY_LIST.getDouble(0));
+ assertEquals(2D, TERTIARY_LIST.getDouble(1));
+ assertEquals(3D, TERTIARY_LIST.getDouble(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, DoubleArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addDouble(3);
+ list.addDouble(4);
+ list.addDouble(6);
+ list.addDouble(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(17D);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addDouble(2);
+ list.addDouble(4);
+
+ assertEquals(2D, (double) list.set(0, 3D));
+ assertEquals(3D, list.getDouble(0));
+
+ assertEquals(4D, (double) list.set(1, 0D));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.set(-1, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0D);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetDouble() {
+ list.addDouble(1);
+ list.addDouble(3);
+
+ assertEquals(1D, list.setDouble(0, 0));
+ assertEquals(0D, list.getDouble(0));
+
+ assertEquals(3D, list.setDouble(1, 0));
+ assertEquals(0D, list.getDouble(1));
+
+ try {
+ list.setDouble(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2D));
+ assertEquals(asList(2D), list);
+
+ assertTrue(list.add(3D));
+ list.add(0, 4D);
+ assertEquals(asList(4D, 2D, 3D), list);
+
+ list.add(0, 1D);
+ list.add(0, 0D);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Double.valueOf(5 + i));
+ }
+ assertEquals(
+ asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D),
+ list);
+
+ try {
+ list.add(-1, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5D);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddDouble() {
+ assertEquals(0, list.size());
+
+ list.addDouble(2);
+ assertEquals(asList(2D), list);
+
+ list.addDouble(3);
+ assertEquals(asList(2D, 3D), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1D)));
+ assertEquals(1, list.size());
+ assertEquals(1D, (double) list.get(0));
+ assertEquals(1D, list.getDouble(0));
+
+ assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D)));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list);
+
+ assertFalse(list.addAll(Collections.<Double>emptyList()));
+ assertFalse(list.addAll(DoubleArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1D, (double) list.remove(0));
+ assertEquals(asList(2D, 3D), list);
+
+ assertTrue(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertFalse(list.remove(Double.valueOf(3)));
+ assertEquals(asList(2D), list);
+
+ assertEquals(2D, (double) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(DoubleArrayList list) {
+ if (list.contains(1D)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new DoubleArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addDouble(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Double>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1D));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0D);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setDouble(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static DoubleArrayList newImmutableDoubleArrayList(double... elements) {
+ DoubleArrayList list = new DoubleArrayList();
+ for (double element : elements) {
+ list.addDouble(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
new file mode 100644
index 0000000000..77d14f6b3a
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -0,0 +1,324 @@
+// 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 com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link DynamicMessage}. See also {@link MessageTest}, which
+ * tests some {@link DynamicMessage} functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class DynamicMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+ TestUtil.ReflectionTester packedReflectionTester =
+ new TestUtil.ReflectionTester(TestPackedTypes.getDescriptor(), null);
+
+ public void testDynamicMessageAccessors() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testSettersAfterBuild() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ Message firstMessage = builder.build();
+ // double build()
+ builder.build();
+ // clear() after build()
+ builder.clear();
+ // setters after build()
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ // repeated setters after build()
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ // firstMessage shouldn't have been modified.
+ reflectionTester.assertClearViaReflection(firstMessage);
+ }
+
+ public void testUnknownFields() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestEmptyMessage.getDescriptor());
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(1, UnknownFieldSet.Field.newBuilder().addVarint(1).build())
+ .addField(2, UnknownFieldSet.Field.newBuilder().addFixed32(1).build())
+ .build());
+ Message message = builder.build();
+ assertEquals(2, message.getUnknownFields().asMap().size());
+ // clone() with unknown fields
+ Message.Builder newBuilder = builder.clone();
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ // clear() with unknown fields
+ newBuilder.clear();
+ assertTrue(newBuilder.getUnknownFields().asMap().isEmpty());
+ // serialize/parse with unknown fields
+ newBuilder.mergeFrom(message.toByteString());
+ assertEquals(2, newBuilder.getUnknownFields().asMap().size());
+ }
+
+ public void testDynamicMessageSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageExtensionAccessors() throws Exception {
+ // We don't need to extensively test DynamicMessage's handling of
+ // extensions because, frankly, it doesn't do anything special with them.
+ // It treats them just like any other fields.
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testDynamicMessageExtensionSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllExtensions.getDescriptor());
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageRepeatedSetters() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ Message message = builder.build();
+ reflectionTester.assertRepeatedFieldsModifiedViaReflection(message);
+ }
+
+ public void testDynamicMessageRepeatedSettersRejectNull() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testDynamicMessageDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.getDefaultInstance(TestAllTypes.getDescriptor()));
+ reflectionTester.assertClearViaReflection(
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor()).build());
+ }
+
+ public void testDynamicMessageSerializedSize() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ Message.Builder dynamicBuilder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(dynamicBuilder);
+ Message dynamicMessage = dynamicBuilder.build();
+
+ assertEquals(message.getSerializedSize(),
+ dynamicMessage.getSerializedSize());
+ }
+
+ public void testDynamicMessageSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getAllSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessageParsing() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ reflectionTester.assertAllFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageExtensionParsing() throws Exception {
+ ByteString rawBytes = TestUtil.getAllExtensionsSet().toByteString();
+ Message message = DynamicMessage.parseFrom(
+ TestAllExtensions.getDescriptor(), rawBytes,
+ TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+
+ // Test Parser interface.
+ Message message2 = message.getParserForType().parseFrom(
+ rawBytes, TestUtil.getExtensionRegistry());
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message2);
+ }
+
+ public void testDynamicMessagePackedSerialization() throws Exception {
+ Message.Builder builder =
+ DynamicMessage.newBuilder(TestPackedTypes.getDescriptor());
+ packedReflectionTester.setPackedFieldsViaReflection(builder);
+ Message message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+
+ // In fact, the serialized forms should be exactly the same, byte-for-byte.
+ assertEquals(TestUtil.getPackedSet().toByteString(), rawBytes);
+ }
+
+ public void testDynamicMessagePackedParsing() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestUtil.setPackedFields(builder);
+ TestPackedTypes message = builder.build();
+
+ ByteString rawBytes = message.toByteString();
+
+ Message message2 =
+ DynamicMessage.parseFrom(TestPackedTypes.getDescriptor(), rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message2);
+
+ // Test Parser interface.
+ Message message3 = message2.getParserForType().parseFrom(rawBytes);
+ packedReflectionTester.assertPackedFieldsSetViaReflection(message3);
+ }
+
+ public void testDynamicMessageCopy() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ DynamicMessage copy = DynamicMessage.newBuilder(message).build();
+ reflectionTester.assertAllFieldsSetViaReflection(copy);
+
+ // Test oneof behavior
+ FieldDescriptor bytesField =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+ FieldDescriptor uint32Field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_uint32");
+ assertTrue(copy.hasField(bytesField));
+ assertFalse(copy.hasField(uint32Field));
+ DynamicMessage copy2 =
+ DynamicMessage.newBuilder(message).setField(uint32Field, 123).build();
+ assertFalse(copy2.hasField(bytesField));
+ assertTrue(copy2.hasField(uint32Field));
+ assertEquals(123, copy2.getField(uint32Field));
+ }
+
+ public void testToBuilder() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ reflectionTester.setAllFieldsViaReflection(builder);
+ int unknownFieldNum = 9;
+ long unknownFieldVal = 90;
+ builder.setUnknownFields(UnknownFieldSet.newBuilder()
+ .addField(unknownFieldNum,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(unknownFieldVal).build())
+ .build());
+ DynamicMessage message = builder.build();
+
+ DynamicMessage derived = message.toBuilder().build();
+ reflectionTester.assertAllFieldsSetViaReflection(derived);
+ assertEquals(Arrays.asList(unknownFieldVal),
+ derived.getUnknownFields().getField(unknownFieldNum).getVarintList());
+ }
+
+ public void testDynamicOneofMessage() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ OneofDescriptor oneof = TestAllTypes.getDescriptor().getOneofs().get(0);
+ assertFalse(builder.hasOneof(oneof));
+ assertSame(null, builder.getOneofFieldDescriptor(oneof));
+
+ reflectionTester.setAllFieldsViaReflection(builder);
+ assertTrue(builder.hasOneof(oneof));
+ FieldDescriptor field = oneof.getField(3);
+ assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+ DynamicMessage message = builder.buildPartial();
+ assertTrue(message.hasOneof(oneof));
+
+ DynamicMessage.Builder mergedBuilder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ FieldDescriptor mergedField = oneof.getField(0);
+ mergedBuilder.setField(mergedField, 123);
+ assertTrue(mergedBuilder.hasField(mergedField));
+ mergedBuilder.mergeFrom(message);
+ assertTrue(mergedBuilder.hasField(field));
+ assertFalse(mergedBuilder.hasField(mergedField));
+
+ builder.clearOneof(oneof);
+ assertSame(null, builder.getOneofFieldDescriptor(oneof));
+ message = builder.build();
+ assertSame(null, message.getOneofFieldDescriptor(oneof));
+ }
+
+ // Regression test for a bug that makes setField() not work for repeated
+ // enum fields.
+ public void testSettersForRepeatedEnumField() throws Exception {
+ DynamicMessage.Builder builder =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
+ FieldDescriptor repeatedEnumField =
+ TestAllTypes.getDescriptor().findFieldByName(
+ "repeated_nested_enum");
+ EnumDescriptor enumDescriptor = TestAllTypes.NestedEnum.getDescriptor();
+ builder.setField(repeatedEnumField, enumDescriptor.getValues());
+ DynamicMessage message = builder.build();
+ assertEquals(
+ enumDescriptor.getValues(), message.getField(repeatedEnumField));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/EnumTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/EnumTest.java
new file mode 100644
index 0000000000..14c7406b3d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/EnumTest.java
@@ -0,0 +1,76 @@
+// 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 com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+public class EnumTest extends TestCase {
+
+ public void testForNumber() {
+ ForeignEnum e = ForeignEnum.forNumber(ForeignEnum.FOREIGN_BAR.getNumber());
+ assertEquals(ForeignEnum.FOREIGN_BAR, e);
+
+ e = ForeignEnum.forNumber(1000);
+ assertEquals(null, e);
+ }
+
+ public void testForNumber_oneof() {
+ TestAllTypes.OneofFieldCase e = TestAllTypes.OneofFieldCase.forNumber(
+ TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber());
+ assertEquals(TestAllTypes.OneofFieldCase.ONEOF_NESTED_MESSAGE, e);
+
+ e = TestAllTypes.OneofFieldCase.forNumber(1000);
+ assertEquals(null, e);
+ }
+
+ public void testForNumberLite() {
+ ForeignEnumLite e = ForeignEnumLite.forNumber(ForeignEnumLite.FOREIGN_LITE_BAR.getNumber());
+ assertEquals(ForeignEnumLite.FOREIGN_LITE_BAR, e);
+
+ e = ForeignEnumLite.forNumber(1000);
+ assertEquals(null, e);
+ }
+
+ public void testForNumberLite_oneof() {
+ TestAllTypesLite.OneofFieldCase e = TestAllTypesLite.OneofFieldCase.forNumber(
+ TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE.getNumber());
+ assertEquals(TestAllTypesLite.OneofFieldCase.ONEOF_NESTED_MESSAGE, e);
+
+ e = TestAllTypesLite.OneofFieldCase.forNumber(1000);
+ assertEquals(null, e);
+ }
+}
+
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
new file mode 100644
index 0000000000..6157e58966
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
@@ -0,0 +1,276 @@
+// 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 protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtensionLite;
+import java.lang.reflect.Method;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry} instances it
+ * creates.
+ *
+ * <p>This test simulates the runtime behaviour of the ExtensionRegistryFactory by delegating test
+ * definitions to two inner classes {@link InnerTest} and {@link InnerLiteTest}, the latter of
+ * which is executed using a custom ClassLoader, simulating the ProtoLite environment.
+ *
+ * <p>The test mechanism employed here is based on the pattern in
+ * {@code com.google.common.util.concurrent.AbstractFutureFallbackAtomicHelperTest}
+ */
+public class ExtensionRegistryFactoryTest extends TestCase {
+
+ // A classloader which blacklists some non-Lite classes.
+ private static final ClassLoader LITE_CLASS_LOADER = getLiteOnlyClassLoader();
+
+ /**
+ * Defines the set of test methods which will be run.
+ */
+ static interface RegistryTests {
+ void testCreate();
+ void testEmpty();
+ void testIsFullRegistry();
+ void testAdd();
+ void testAdd_immutable();
+ }
+
+ /**
+ * Test implementations for the non-Lite usage of ExtensionRegistryFactory.
+ */
+ public static class InnerTest implements RegistryTests {
+
+ @Override
+ public void testCreate() {
+ ExtensionRegistryLite registry = ExtensionRegistryFactory.create();
+
+ assertEquals(registry.getClass(), ExtensionRegistry.class);
+ }
+
+ @Override
+ public void testEmpty() {
+ ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty();
+
+ assertEquals(emptyRegistry.getClass(), ExtensionRegistry.class);
+ assertEquals(emptyRegistry, ExtensionRegistry.EMPTY_REGISTRY);
+ }
+
+ @Override
+ public void testIsFullRegistry() {
+ ExtensionRegistryLite registry = ExtensionRegistryFactory.create();
+ assertTrue(ExtensionRegistryFactory.isFullRegistry(registry));
+ }
+
+ @Override
+ public void testAdd() {
+ ExtensionRegistryLite registry1 = ExtensionRegistryLite.newInstance();
+ NonNestedExtensionLite.registerAllExtensions(registry1);
+ registry1.add(NonNestedExtensionLite.nonNestedExtensionLite);
+
+ ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance();
+ NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2);
+ registry2.add(NonNestedExtension.nonNestedExtension);
+
+ ExtensionRegistry fullRegistry1 = (ExtensionRegistry) registry1;
+ ExtensionRegistry fullRegistry2 = (ExtensionRegistry) registry2;
+
+ assertTrue("Test is using a non-lite extension",
+ GeneratedMessageLite.GeneratedExtension.class.isAssignableFrom(
+ NonNestedExtensionLite.nonNestedExtensionLite.getClass()));
+ assertNull("Extension is not registered in masqueraded full registry",
+ fullRegistry1.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension"));
+ GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLiteToBeExtended, ?>
+ extension = registry1.findLiteExtensionByNumber(
+ NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1);
+ assertNotNull("Extension registered in lite registry", extension);
+
+ assertTrue("Test is using a non-lite extension",
+ GeneratedMessage.GeneratedExtension.class.isAssignableFrom(
+ NonNestedExtension.nonNestedExtension.getClass()));
+ assertNotNull("Extension is registered in masqueraded full registry",
+ fullRegistry2.findImmutableExtensionByName("protobuf_unittest.nonNestedExtension"));
+ }
+
+ @Override
+ public void testAdd_immutable() {
+ ExtensionRegistryLite registry1 = ExtensionRegistryLite.newInstance().getUnmodifiable();
+ try {
+ NonNestedExtensionLite.registerAllExtensions(registry1);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ try {
+ registry1.add(NonNestedExtensionLite.nonNestedExtensionLite);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ ExtensionRegistryLite registry2 = ExtensionRegistryLite.newInstance().getUnmodifiable();
+ try {
+ NonNestedExtension.registerAllExtensions((ExtensionRegistry) registry2);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ try {
+ registry2.add(NonNestedExtension.nonNestedExtension);
+ fail();
+ } catch (IllegalArgumentException expected) {}
+ }
+ }
+
+ /**
+ * Test implementations for the Lite usage of ExtensionRegistryFactory.
+ */
+ public static final class InnerLiteTest implements RegistryTests {
+
+ @Override
+ public void testCreate() {
+ ExtensionRegistryLite registry = ExtensionRegistryFactory.create();
+
+ assertEquals(registry.getClass(), ExtensionRegistryLite.class);
+ }
+
+ @Override
+ public void testEmpty() {
+ ExtensionRegistryLite emptyRegistry = ExtensionRegistryFactory.createEmpty();
+
+ assertEquals(emptyRegistry.getClass(), ExtensionRegistryLite.class);
+ assertEquals(emptyRegistry, ExtensionRegistryLite.EMPTY_REGISTRY_LITE);
+ }
+
+ @Override
+ public void testIsFullRegistry() {
+ ExtensionRegistryLite registry = ExtensionRegistryFactory.create();
+ assertFalse(ExtensionRegistryFactory.isFullRegistry(registry));
+ }
+
+ @Override
+ public void testAdd() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ NonNestedExtensionLite.registerAllExtensions(registry);
+ GeneratedMessageLite.GeneratedExtension<NonNestedExtensionLite.MessageLiteToBeExtended, ?>
+ extension = registry.findLiteExtensionByNumber(
+ NonNestedExtensionLite.MessageLiteToBeExtended.getDefaultInstance(), 1);
+ assertNotNull("Extension is registered in Lite registry", extension);
+ }
+
+ @Override
+ public void testAdd_immutable() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance().getUnmodifiable();
+ try {
+ NonNestedExtensionLite.registerAllExtensions(registry);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+ }
+
+ /**
+ * Defines a suite of tests which the JUnit3 runner retrieves by reflection.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ for (Method method : RegistryTests.class.getMethods()) {
+ suite.addTest(TestSuite.createTest(ExtensionRegistryFactoryTest.class, method.getName()));
+ }
+ return suite;
+ }
+
+ /**
+ * Sequentially runs first the Lite and then the non-Lite test variant via classloader
+ * manipulation.
+ */
+ @Override
+ public void runTest() throws Exception {
+ ClassLoader storedClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(LITE_CLASS_LOADER);
+ try {
+ runTestMethod(LITE_CLASS_LOADER, InnerLiteTest.class);
+ } finally {
+ Thread.currentThread().setContextClassLoader(storedClassLoader);
+ }
+ try {
+ runTestMethod(storedClassLoader, InnerTest.class);
+ } finally {
+ Thread.currentThread().setContextClassLoader(storedClassLoader);
+ }
+ }
+
+ private void runTestMethod(ClassLoader classLoader, Class<? extends RegistryTests> testClass)
+ throws Exception {
+ classLoader.loadClass(ExtensionRegistryFactory.class.getName());
+ Class<?> test = classLoader.loadClass(testClass.getName());
+ String testName = getName();
+ test.getMethod(testName).invoke(test.newInstance());
+ }
+
+ /**
+ * Constructs a custom ClassLoader blacklisting the classes which are inspected in the SUT
+ * to determine the Lite/non-Lite runtime.
+ */
+ private static ClassLoader getLiteOnlyClassLoader() {
+ ClassLoader testClassLoader = ExtensionRegistryFactoryTest.class.getClassLoader();
+ final Set<String> classNamesNotInLite =
+ Collections.unmodifiableSet(
+ new HashSet<String>(
+ Arrays.asList(
+ ExtensionRegistryFactory.FULL_REGISTRY_CLASS_NAME,
+ ExtensionRegistry.EXTENSION_CLASS_NAME)));
+
+ // Construct a URLClassLoader delegating to the system ClassLoader, and looking up classes
+ // in jar files based on the URLs already configured for this test's UrlClassLoader.
+ // Certain classes throw a ClassNotFoundException by design.
+ return new URLClassLoader(((URLClassLoader) testClassLoader).getURLs(),
+ ClassLoader.getSystemClassLoader()) {
+ @Override
+ public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ if (classNamesNotInLite.contains(name)) {
+ throw new ClassNotFoundException("Class deliberately blacklisted by test.");
+ }
+ Class<?> loadedClass = null;
+ try {
+ loadedClass = findLoadedClass(name);
+ if (loadedClass == null) {
+ loadedClass = findClass(name);
+ if (resolve) {
+ resolveClass(loadedClass);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ loadedClass = super.loadClass(name, resolve);
+ }
+ return loadedClass;
+ }
+ };
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
new file mode 100644
index 0000000000..4a42c8970e
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -0,0 +1,443 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
+import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
+import protobuf_unittest.UnittestProto;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that doesn't support field presence test for optional
+ * non-message fields.
+ */
+public class FieldPresenceTest extends TestCase {
+ private static boolean hasMethod(Class<?> clazz, String name) {
+ try {
+ if (clazz.getMethod(name) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ private static void assertHasMethodRemoved(
+ Class<?> classWithFieldPresence,
+ Class<?> classWithoutFieldPresence,
+ String camelName) {
+ assertTrue(hasMethod(classWithFieldPresence, "get" + camelName));
+ assertTrue(hasMethod(classWithFieldPresence, "has" + camelName));
+ assertTrue(hasMethod(classWithoutFieldPresence, "get" + camelName));
+ assertFalse(hasMethod(classWithoutFieldPresence, "has" + camelName));
+ }
+
+ public void testHasMethod() {
+ // Optional non-message fields don't have a hasFoo() method generated.
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalInt32");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalString");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalBytes");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OptionalNestedEnum");
+
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalInt32");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalString");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalBytes");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OptionalNestedEnum");
+
+ // message fields still have the hasFoo() method generated.
+ assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
+ assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
+
+ // oneof fields don't have hasFoo() methods (even for message types).
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofUint32");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofString");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofBytes");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.class,
+ TestAllTypes.class,
+ "OneofNestedMessage");
+
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofUint32");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofString");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofBytes");
+ assertHasMethodRemoved(
+ UnittestProto.TestAllTypes.Builder.class,
+ TestAllTypes.Builder.class,
+ "OneofNestedMessage");
+ }
+
+ public void testOneofEquals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message1 = builder.build();
+ // Set message2's oneof_uint32 field to defalut value. The two
+ // messages should be different when check with oneof case.
+ builder.setOneofUint32(0);
+ TestAllTypes message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
+ public void testLazyField() throws Exception {
+ // Test default constructed message.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message = builder.build();
+ assertFalse(message.hasOptionalLazyMessage());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(ByteString.EMPTY, message.toByteString());
+
+ // Set default instance to the field.
+ builder.setOptionalLazyMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ message = builder.build();
+ assertTrue(message.hasOptionalLazyMessage());
+ assertEquals(2, message.getSerializedSize());
+
+ // Test parse zero-length from wire sets the presence.
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteString());
+ assertTrue(parsed.hasOptionalLazyMessage());
+ assertEquals(message.getOptionalLazyMessage(), parsed.getOptionalLazyMessage());
+ }
+
+ public void testFieldPresence() {
+ // Optional non-message fields set to their default value are treated the
+ // same way as not set.
+
+ // Serialization will ignore such fields.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(0);
+ builder.setOptionalString("");
+ builder.setOptionalBytes(ByteString.EMPTY);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ TestAllTypes message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+
+ // mergeFrom() will ignore such fields.
+ TestAllTypes.Builder a = TestAllTypes.newBuilder();
+ a.setOptionalInt32(1);
+ a.setOptionalString("x");
+ a.setOptionalBytes(ByteString.copyFromUtf8("y"));
+ a.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ TestAllTypes.Builder b = TestAllTypes.newBuilder();
+ b.setOptionalInt32(0);
+ b.setOptionalString("");
+ b.setOptionalBytes(ByteString.EMPTY);
+ b.setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO);
+ a.mergeFrom(b.build());
+ message = a.build();
+ assertEquals(1, message.getOptionalInt32());
+ assertEquals("x", message.getOptionalString());
+ assertEquals(ByteString.copyFromUtf8("y"), message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
+
+ // equals()/hashCode() should produce the same results.
+ TestAllTypes empty = TestAllTypes.newBuilder().build();
+ message = builder.build();
+ assertTrue(empty.equals(message));
+ assertTrue(message.equals(empty));
+ assertEquals(empty.hashCode(), message.hashCode());
+ }
+
+ public void testFieldPresenceByReflection() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+
+ // Field not present.
+ TestAllTypes message = TestAllTypes.newBuilder().build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to default value is seen as not present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(0)
+ .setOptionalString("")
+ .setOptionalBytes(ByteString.EMPTY)
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.FOO)
+ .build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to non-default value is seen as present.
+ message = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("x")
+ .setOptionalBytes(ByteString.copyFromUtf8("y"))
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR)
+ .build();
+ assertTrue(message.hasField(optionalInt32Field));
+ assertTrue(message.hasField(optionalStringField));
+ assertTrue(message.hasField(optionalBytesField));
+ assertTrue(message.hasField(optionalNestedEnumField));
+ assertEquals(4, message.getAllFields().size());
+ }
+
+ public void testFieldPresenceDynamicMessage() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalInt32Field = descriptor.findFieldByName("optional_int32");
+ FieldDescriptor optionalStringField = descriptor.findFieldByName("optional_string");
+ FieldDescriptor optionalBytesField = descriptor.findFieldByName("optional_bytes");
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ EnumDescriptor enumDescriptor = optionalNestedEnumField.getEnumType();
+ EnumValueDescriptor defaultEnumValueDescriptor = enumDescriptor.getValues().get(0);
+ EnumValueDescriptor nonDefaultEnumValueDescriptor = enumDescriptor.getValues().get(1);
+
+ DynamicMessage defaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+ // Field not present.
+ DynamicMessage message = defaultInstance.newBuilderForType().build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+
+ // Field set to non-default value is seen as present.
+ message =
+ defaultInstance
+ .newBuilderForType()
+ .setField(optionalInt32Field, 1)
+ .setField(optionalStringField, "x")
+ .setField(optionalBytesField, ByteString.copyFromUtf8("y"))
+ .setField(optionalNestedEnumField, nonDefaultEnumValueDescriptor)
+ .build();
+ assertTrue(message.hasField(optionalInt32Field));
+ assertTrue(message.hasField(optionalStringField));
+ assertTrue(message.hasField(optionalBytesField));
+ assertTrue(message.hasField(optionalNestedEnumField));
+ assertEquals(4, message.getAllFields().size());
+
+ // Field set to default value is seen as not present.
+ message = message.toBuilder()
+ .setField(optionalInt32Field, 0)
+ .setField(optionalStringField, "")
+ .setField(optionalBytesField, ByteString.EMPTY)
+ .setField(optionalNestedEnumField, defaultEnumValueDescriptor)
+ .build();
+ assertFalse(message.hasField(optionalInt32Field));
+ assertFalse(message.hasField(optionalStringField));
+ assertFalse(message.hasField(optionalBytesField));
+ assertFalse(message.hasField(optionalNestedEnumField));
+ assertEquals(0, message.getAllFields().size());
+ }
+
+ public void testMessageField() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ TestAllTypes.NestedMessage.Builder nestedBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+
+ nestedBuilder.setValue(1);
+ assertEquals(1, builder.build().getOptionalNestedMessage().getValue());
+
+ builder.clearOptionalNestedMessage();
+ assertFalse(builder.hasOptionalNestedMessage());
+ assertFalse(builder.build().hasOptionalNestedMessage());
+
+ // Unlike non-message fields, if we set a message field to its default value (i.e.,
+ // default instance), the field should be seen as present.
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ assertTrue(builder.hasOptionalNestedMessage());
+ assertTrue(builder.build().hasOptionalNestedMessage());
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ // Set an oneof field to its default value and expect it to be serialized (i.e.,
+ // an oneof field set to the default value should be treated as present).
+ builder.setOneofInt32(0);
+ ByteString data = builder.build().toByteString();
+
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(1234, message.getOptionalInt32());
+ assertEquals("hello", message.getOptionalString());
+ // Fields not set will have the default value.
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum());
+ // The message field is set despite that it's set with a default instance.
+ assertTrue(message.hasOptionalNestedMessage());
+ assertEquals(0, message.getOptionalNestedMessage().getValue());
+ // The oneof field set to its default value is also present.
+ assertEquals(
+ TestAllTypes.OneofFieldCase.ONEOF_INT32, message.getOneofFieldCase());
+ }
+
+ // Regression test for b/16173397
+ // Make sure we haven't screwed up the code generation for repeated fields.
+ public void testRepeatedFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.setOptionalString("hello");
+ builder.setOptionalNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ builder.addRepeatedInt32(4321);
+ builder.addRepeatedString("world");
+ builder.addRepeatedNestedMessage(TestAllTypes.NestedMessage.getDefaultInstance());
+ ByteString data = builder.build().toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage = TestOptionalFieldsOnly.parseFrom(data);
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ assertEquals("hello", optionalOnlyMessage.getOptionalString());
+ assertTrue(optionalOnlyMessage.hasOptionalNestedMessage());
+ assertEquals(0, optionalOnlyMessage.getOptionalNestedMessage().getValue());
+
+ TestRepeatedFieldsOnly repeatedOnlyMessage = TestRepeatedFieldsOnly.parseFrom(data);
+ assertEquals(1, repeatedOnlyMessage.getRepeatedInt32Count());
+ assertEquals(4321, repeatedOnlyMessage.getRepeatedInt32(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedStringCount());
+ assertEquals("world", repeatedOnlyMessage.getRepeatedString(0));
+ assertEquals(1, repeatedOnlyMessage.getRepeatedNestedMessageCount());
+ assertEquals(0, repeatedOnlyMessage.getRepeatedNestedMessage(0).getValue());
+ }
+
+ public void testIsInitialized() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // Test optional proto2 message fields.
+ UnittestProto.TestRequired.Builder proto2Builder =
+ builder.getOptionalProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test oneof proto2 message fields.
+ proto2Builder = builder.getOneofProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+
+ // Test repeated proto2 message fields.
+ proto2Builder = builder.addRepeatedProto2MessageBuilder();
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ proto2Builder.setA(1).setB(2).setC(3);
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+
+ // Test that unknown fields are dropped.
+ public void testUnknownFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalInt32(1234);
+ builder.addRepeatedInt32(5678);
+ TestAllTypes message = builder.build();
+ ByteString data = message.toByteString();
+
+ TestOptionalFieldsOnly optionalOnlyMessage =
+ TestOptionalFieldsOnly.parseFrom(data);
+ // UnknownFieldSet should be empty.
+ assertEquals(
+ 0, optionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(1234, optionalOnlyMessage.getOptionalInt32());
+ message = TestAllTypes.parseFrom(optionalOnlyMessage.toByteString());
+ assertEquals(1234, message.getOptionalInt32());
+ // The repeated field is discarded because it's unknown to the optional-only
+ // message.
+ assertEquals(0, message.getRepeatedInt32Count());
+
+ DynamicMessage dynamicOptionalOnlyMessage =
+ DynamicMessage.getDefaultInstance(
+ TestOptionalFieldsOnly.getDescriptor())
+ .getParserForType().parseFrom(data);
+ assertEquals(
+ 0, dynamicOptionalOnlyMessage.getUnknownFields().toByteString().size());
+ assertEquals(optionalOnlyMessage.toByteString(),
+ dynamicOptionalOnlyMessage.toByteString());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
new file mode 100644
index 0000000000..aa36be4977
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java
@@ -0,0 +1,461 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link FloatArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class FloatArrayListTest extends TestCase {
+
+ private static final FloatArrayList UNARY_LIST =
+ newImmutableFloatArrayList(1);
+ private static final FloatArrayList TERTIARY_LIST =
+ newImmutableFloatArrayList(1, 2, 3);
+
+ private FloatArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new FloatArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(FloatArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addFloat(3);
+ list.addFloat(4);
+ list.addFloat(5);
+ list.addFloat(7);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1F, 2F, 3F, 4F));
+ Iterator<Float> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, (float) iterator.next());
+ list.set(0, 1F);
+ assertEquals(2F, (float) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0F);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1F, (float) TERTIARY_LIST.get(0));
+ assertEquals(2F, (float) TERTIARY_LIST.get(1));
+ assertEquals(3F, (float) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetFloat() {
+ assertEquals(1F, TERTIARY_LIST.getFloat(0));
+ assertEquals(2F, TERTIARY_LIST.getFloat(1));
+ assertEquals(3F, TERTIARY_LIST.getFloat(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, FloatArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addFloat(3);
+ list.addFloat(4);
+ list.addFloat(6);
+ list.addFloat(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(17F);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addFloat(2);
+ list.addFloat(4);
+
+ assertEquals(2F, (float) list.set(0, 3F));
+ assertEquals(3F, list.getFloat(0));
+
+ assertEquals(4F, (float) list.set(1, 0F));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.set(-1, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0F);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetFloat() {
+ list.addFloat(1);
+ list.addFloat(3);
+
+ assertEquals(1F, list.setFloat(0, 0));
+ assertEquals(0F, list.getFloat(0));
+
+ assertEquals(3F, list.setFloat(1, 0));
+ assertEquals(0F, list.getFloat(1));
+
+ try {
+ list.setFloat(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2F));
+ assertEquals(asList(2F), list);
+
+ assertTrue(list.add(3F));
+ list.add(0, 4F);
+ assertEquals(asList(4F, 2F, 3F), list);
+
+ list.add(0, 1F);
+ list.add(0, 0F);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Float.valueOf(5 + i));
+ }
+ assertEquals(
+ asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F),
+ list);
+
+ try {
+ list.add(-1, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5F);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddFloat() {
+ assertEquals(0, list.size());
+
+ list.addFloat(2);
+ assertEquals(asList(2F), list);
+
+ list.addFloat(3);
+ assertEquals(asList(2F, 3F), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1F)));
+ assertEquals(1, list.size());
+ assertEquals(1F, (float) list.get(0));
+ assertEquals(1F, list.getFloat(0));
+
+ assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F)));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list);
+
+ assertFalse(list.addAll(Collections.<Float>emptyList()));
+ assertFalse(list.addAll(FloatArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1F, (float) list.remove(0));
+ assertEquals(asList(2F, 3F), list);
+
+ assertTrue(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertFalse(list.remove(Float.valueOf(3)));
+ assertEquals(asList(2F), list);
+
+ assertEquals(2F, (float) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(FloatArrayList list) {
+ if (list.contains(1F)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new FloatArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addFloat(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Float>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1F));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0F);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setFloat(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static FloatArrayList newImmutableFloatArrayList(float... elements) {
+ FloatArrayList list = new FloatArrayList();
+ for (float element : elements) {
+ list.addFloat(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
new file mode 100644
index 0000000000..b7eaebf5e2
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ForceFieldBuildersPreRun.java
@@ -0,0 +1,48 @@
+// 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;
+
+/**
+ * A prerun for a test suite that allows running the full protocol buffer
+ * tests in a mode that disables the optimization for not using
+ * {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder} until they are
+ * requested. This allows us to run all the tests through both code paths
+ * and ensures that both code paths produce identical results.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class ForceFieldBuildersPreRun implements Runnable {
+
+ @Override
+ public void run() {
+ GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
new file mode 100644
index 0000000000..3eece26a4a
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -0,0 +1,1674 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.test.UnittestImport;
+import protobuf_unittest.EnumWithNoOuter;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.MultipleFilesTestProto;
+import protobuf_unittest.NestedExtension.MyNestedExtension;
+import protobuf_unittest.NestedExtensionLite.MyNestedExtensionLite;
+import protobuf_unittest.NonNestedExtension;
+import protobuf_unittest.NonNestedExtension.MessageToBeExtended;
+import protobuf_unittest.NonNestedExtension.MyNonNestedExtension;
+import protobuf_unittest.NonNestedExtensionLite;
+import protobuf_unittest.NonNestedExtensionLite.MessageLiteToBeExtended;
+import protobuf_unittest.NonNestedExtensionLite.MyNonNestedExtensionLite;
+import protobuf_unittest.OuterClassNameTest2OuterClass;
+import protobuf_unittest.OuterClassNameTest3OuterClass;
+import protobuf_unittest.OuterClassNameTestOuterClass;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestOptionalOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestExtremeDefaultValues;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for generated messages and generated code. See also
+ * {@link MessageTest}, which tests some generated message functionality.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class GeneratedMessageTest extends TestCase {
+ TestUtil.ReflectionTester reflectionTester =
+ new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
+
+ public void testDefaultInstance() throws Exception {
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.getDefaultInstance().getDefaultInstanceForType());
+ assertSame(TestAllTypes.getDefaultInstance(),
+ TestAllTypes.newBuilder().getDefaultInstanceForType());
+ }
+
+ public void testMessageOrBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testUsingBuilderMultipleTimes() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // primitive field scalar and repeated
+ builder.setOptionalSfixed64(100);
+ builder.addRepeatedInt32(100);
+ // enum field scalar and repeated
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ // proto field scalar and repeated
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(1));
+ builder.addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(1));
+
+ TestAllTypes value1 = builder.build();
+
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure that builder didn't update previously created values
+ builder.setOptionalSfixed64(200);
+ builder.setRepeatedInt32(0, 200);
+ builder.setOptionalImportEnum(UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setRepeatedImportEnum(0, UnittestImport.ImportEnum.IMPORT_FOO);
+ builder.setOptionalForeignMessage(ForeignMessage.newBuilder().setC(2));
+ builder.setRepeatedForeignMessage(0, ForeignMessage.newBuilder().setC(2));
+
+ TestAllTypes value2 = builder.build();
+
+ // Make sure value1 didn't change.
+ assertEquals(100, value1.getOptionalSfixed64());
+ assertEquals(100, value1.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_BAR,
+ value1.getRepeatedImportEnum(0));
+ assertEquals(1, value1.getOptionalForeignMessage().getC());
+ assertEquals(1, value1.getRepeatedForeignMessage(0).getC());
+
+ // Make sure value2 is correct
+ assertEquals(200, value2.getOptionalSfixed64());
+ assertEquals(200, value2.getRepeatedInt32(0));
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getOptionalImportEnum());
+ assertEquals(UnittestImport.ImportEnum.IMPORT_FOO,
+ value2.getRepeatedImportEnum(0));
+ assertEquals(2, value2.getOptionalForeignMessage().getC());
+ assertEquals(2, value2.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testProtosShareRepeatedArraysIfDidntChange() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedInt32(100);
+ builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+
+ TestAllTypes value1 = builder.build();
+ TestAllTypes value2 = value1.toBuilder().build();
+
+ assertSame(value1.getRepeatedInt32List(), value2.getRepeatedInt32List());
+ assertSame(value1.getRepeatedForeignMessageList(),
+ value2.getRepeatedForeignMessageList());
+ }
+
+ public void testRepeatedArraysAreImmutable() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedInt32(100);
+ builder.addRepeatedImportEnum(UnittestImport.ImportEnum.IMPORT_BAR);
+ builder.addRepeatedForeignMessage(ForeignMessage.getDefaultInstance());
+ assertIsUnmodifiable(builder.getRepeatedInt32List());
+ assertIsUnmodifiable(builder.getRepeatedImportEnumList());
+ assertIsUnmodifiable(builder.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(builder.getRepeatedFloatList());
+
+
+ TestAllTypes value = builder.build();
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ }
+
+ public void testParsedMessagesAreImmutable() throws Exception {
+ TestAllTypes value = TestAllTypes.parser().parseFrom(TestUtil.getAllSet().toByteString());
+ assertIsUnmodifiable(value.getRepeatedInt32List());
+ assertIsUnmodifiable(value.getRepeatedInt64List());
+ assertIsUnmodifiable(value.getRepeatedUint32List());
+ assertIsUnmodifiable(value.getRepeatedUint64List());
+ assertIsUnmodifiable(value.getRepeatedSint32List());
+ assertIsUnmodifiable(value.getRepeatedSint64List());
+ assertIsUnmodifiable(value.getRepeatedFixed32List());
+ assertIsUnmodifiable(value.getRepeatedFixed64List());
+ assertIsUnmodifiable(value.getRepeatedSfixed32List());
+ assertIsUnmodifiable(value.getRepeatedSfixed64List());
+ assertIsUnmodifiable(value.getRepeatedFloatList());
+ assertIsUnmodifiable(value.getRepeatedDoubleList());
+ assertIsUnmodifiable(value.getRepeatedBoolList());
+ assertIsUnmodifiable(value.getRepeatedStringList());
+ assertIsUnmodifiable(value.getRepeatedBytesList());
+ assertIsUnmodifiable(value.getRepeatedGroupList());
+ assertIsUnmodifiable(value.getRepeatedNestedMessageList());
+ assertIsUnmodifiable(value.getRepeatedForeignMessageList());
+ assertIsUnmodifiable(value.getRepeatedImportMessageList());
+ assertIsUnmodifiable(value.getRepeatedNestedEnumList());
+ assertIsUnmodifiable(value.getRepeatedForeignEnumList());
+ assertIsUnmodifiable(value.getRepeatedImportEnumList());
+ }
+
+ private void assertIsUnmodifiable(List<?> list) {
+ if (list == Collections.emptyList()) {
+ // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+ } else {
+ try {
+ list.clear();
+ fail("List wasn't immutable");
+ } catch (UnsupportedOperationException e) {
+ // good
+ }
+ }
+ }
+
+ public void testSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.setOptionalString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setOptionalNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedString(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedBytes(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage((TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedMessage(
+ (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedNestedEnum(null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestUtil.modifyRepeatedFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addRepeatedString("one");
+ builder.addRepeatedString("two");
+ try {
+ builder.setRepeatedString(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedBytes(TestUtil.toBytes("one"));
+ builder.addRepeatedBytes(TestUtil.toBytes("two"));
+ try {
+ builder.setRepeatedBytes(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(456).build());
+ try {
+ builder.setRepeatedNestedMessage(1, (TestAllTypes.NestedMessage) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setRepeatedNestedMessage(
+ 1, (TestAllTypes.NestedMessage.Builder) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.FOO);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ try {
+ builder.setRepeatedNestedEnum(1, null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedAppend() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ builder.addAllRepeatedInt32(Arrays.asList(1, 2, 3, 4));
+ builder.addAllRepeatedForeignEnum(Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ builder.addAllRepeatedForeignMessage(Arrays.asList(foreignMessage));
+
+ TestAllTypes message = builder.build();
+ assertEquals(message.getRepeatedInt32List(), Arrays.asList(1, 2, 3, 4));
+ assertEquals(message.getRepeatedForeignEnumList(),
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ));
+ assertEquals(1, message.getRepeatedForeignMessageCount());
+ assertEquals(12, message.getRepeatedForeignMessage(0).getC());
+ }
+
+ public void testRepeatedAppendRejectsNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ ForeignMessage foreignMessage =
+ ForeignMessage.newBuilder().setC(12).build();
+ try {
+ builder.addAllRepeatedForeignMessage(
+ Arrays.asList(foreignMessage, (ForeignMessage) null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedForeignEnum(
+ Arrays.asList(ForeignEnum.FOREIGN_BAZ, null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedString(Arrays.asList("one", null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addAllRepeatedBytes(Arrays.asList(TestUtil.toBytes("one"), null));
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testRepeatedAppendIterateOnlyOnce() throws Exception {
+ // Create a Iterable that can only be iterated once.
+ Iterable<String> stringIterable = new Iterable<String>() {
+ private boolean called = false;
+ @Override
+ public Iterator<String> iterator() {
+ if (called) {
+ throw new IllegalStateException();
+ }
+ called = true;
+ return Arrays.asList("one", "two", "three").iterator();
+ }
+ };
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addAllRepeatedString(stringIterable);
+ assertEquals(3, builder.getRepeatedStringCount());
+ assertEquals("one", builder.getRepeatedString(0));
+ assertEquals("two", builder.getRepeatedString(1));
+ assertEquals("three", builder.getRepeatedString(2));
+
+ try {
+ builder.addAllRepeatedString(stringIterable);
+ fail("Exception was not thrown");
+ } catch (IllegalStateException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testMergeFromOtherRejectsNull() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.mergeFrom((TestAllTypes) null);
+ fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ public void testSettingForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(123))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(123).build())
+ .build();
+ // TODO(ngd): Upgrade to using real #equals method once implemented
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testSettingRepeatedForeignMessageUsingBuilder() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder()
+ // Pass builder for foreign message instance.
+ .addRepeatedForeignMessage(ForeignMessage.newBuilder().setC(456))
+ .build();
+ TestAllTypes expectedMessage = TestAllTypes.newBuilder()
+ // Create expected version passing foreign message instance explicitly.
+ .addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(456).build())
+ .build();
+ assertEquals(expectedMessage.toString(), message.toString());
+ }
+
+ public void testDefaults() throws Exception {
+ TestUtil.assertClear(TestAllTypes.getDefaultInstance());
+ TestUtil.assertClear(TestAllTypes.newBuilder().build());
+
+ TestExtremeDefaultValues message =
+ TestExtremeDefaultValues.getDefaultInstance();
+ assertEquals("\u1234", message.getUtf8String());
+ assertEquals(Double.POSITIVE_INFINITY, message.getInfDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, message.getNegInfDouble());
+ assertTrue(Double.isNaN(message.getNanDouble()));
+ assertEquals(Float.POSITIVE_INFINITY, message.getInfFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, message.getNegInfFloat());
+ assertTrue(Float.isNaN(message.getNanFloat()));
+ assertEquals("? ? ?? ?? ??? ??/ ??-", message.getCppTrigraph());
+ }
+
+ public void testClear() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.assertClear(builder);
+ TestUtil.setAllFields(builder);
+ builder.clear();
+ TestUtil.assertClear(builder);
+ }
+
+ public void testReflectionGetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ reflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllTypes message = builder.build();
+ reflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testReflectionSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllFieldsSet(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ }
+
+ public void testReflectionSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testReflectionRepeatedSetters() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ reflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedFieldsModified(builder);
+
+ TestAllTypes message = builder.build();
+ TestUtil.assertRepeatedFieldsModified(message);
+ }
+
+ public void testReflectionRepeatedSettersRejectNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.assertReflectionRepeatedSettersRejectNull(builder);
+ }
+
+ public void testReflectionDefaults() throws Exception {
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.getDefaultInstance());
+ reflectionTester.assertClearViaReflection(
+ TestAllTypes.newBuilder().build());
+ }
+
+ public void testReflectionGetOneof() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Descriptors.OneofDescriptor oneof =
+ TestAllTypes.getDescriptor().getOneofs().get(0);
+ Descriptors.FieldDescriptor field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+ assertSame(field, builder.getOneofFieldDescriptor(oneof));
+
+ TestAllTypes message = builder.build();
+ assertSame(field, message.getOneofFieldDescriptor(oneof));
+ }
+
+ public void testReflectionClearOneof() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ reflectionTester.setAllFieldsViaReflection(builder);
+ Descriptors.OneofDescriptor oneof =
+ TestAllTypes.getDescriptor().getOneofs().get(0);
+ Descriptors.FieldDescriptor field =
+ TestAllTypes.getDescriptor().findFieldByName("oneof_bytes");
+
+ assertTrue(builder.hasOneof(oneof));
+ assertTrue(builder.hasField(field));
+ builder.clearOneof(oneof);
+ assertFalse(builder.hasOneof(oneof));
+ assertFalse(builder.hasField(field));
+ }
+
+ public void testEnumInterface() throws Exception {
+ assertTrue(TestAllTypes.getDefaultInstance().getDefaultNestedEnum()
+ instanceof ProtocolMessageEnum);
+ }
+
+ public void testEnumMap() throws Exception {
+ Internal.EnumLiteMap<ForeignEnum> map = ForeignEnum.internalGetValueMap();
+
+ for (ForeignEnum value : ForeignEnum.values()) {
+ assertEquals(value, map.findValueByNumber(value.getNumber()));
+ }
+
+ assertTrue(map.findValueByNumber(12345) == null);
+ }
+
+ public void testParsePackedToUnpacked() throws Exception {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ TestUnpackedTypes message =
+ builder.mergeFrom(TestUtil.getPackedSet().toByteString()).build();
+ TestUtil.assertUnpackedFieldsSet(message);
+ }
+
+ public void testParseUnpackedToPacked() throws Exception {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ TestPackedTypes message =
+ builder.mergeFrom(TestUtil.getUnpackedSet().toByteString()).build();
+ TestUtil.assertPackedFieldsSet(message);
+ }
+
+ // =================================================================
+ // Extensions.
+
+ TestUtil.ReflectionTester extensionsReflectionTester =
+ new TestUtil.ReflectionTester(TestAllExtensions.getDescriptor(),
+ TestUtil.getExtensionRegistry());
+
+ public void testExtensionMessageOrBuilder() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ TestUtil.modifyRepeatedExtensions(builder);
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensions.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensions.newBuilder().build());
+ }
+
+ public void testUnsetRepeatedExtensionGetField() {
+ TestAllExtensions message = TestAllExtensions.getDefaultInstance();
+ Object value;
+
+ value = message.getField(UnittestProto.repeatedStringExtension.getDescriptor());
+ assertTrue(value instanceof List);
+ assertTrue(((List<?>) value).isEmpty());
+ assertIsUnmodifiable((List<?>) value);
+
+ value = message.getField(UnittestProto.repeatedNestedMessageExtension.getDescriptor());
+ assertTrue(value instanceof List);
+ assertTrue(((List<?>) value).isEmpty());
+ assertIsUnmodifiable((List<?>) value);
+ }
+
+ public void testExtensionReflectionGetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TestUtil.setAllExtensions(builder);
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(builder);
+
+ TestAllExtensions message = builder.build();
+ extensionsReflectionTester.assertAllFieldsSetViaReflection(message);
+ }
+
+ public void testExtensionReflectionSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ TestUtil.assertAllExtensionsSet(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testExtensionReflectionSettersRejectNull() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionSettersRejectNull(builder);
+ }
+
+ public void testExtensionReflectionRepeatedSetters() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.setAllFieldsViaReflection(builder);
+ extensionsReflectionTester.modifyRepeatedFieldsViaReflection(builder);
+ TestUtil.assertRepeatedExtensionsModified(builder);
+
+ TestAllExtensions message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testExtensionReflectionRepeatedSettersRejectNull()
+ throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ extensionsReflectionTester.assertReflectionRepeatedSettersRejectNull(
+ builder);
+ }
+
+ public void testExtensionReflectionDefaults() throws Exception {
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.getDefaultInstance());
+ extensionsReflectionTester.assertClearViaReflection(
+ TestAllExtensions.newBuilder().build());
+ }
+
+ public void testClearExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1)
+ .clearExtension(UnittestProto.optionalInt32Extension)
+ .hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(0,
+ TestAllExtensions.newBuilder()
+ .addExtension(UnittestProto.repeatedInt32Extension, 1)
+ .clearExtension(UnittestProto.repeatedInt32Extension)
+ .getExtensionCount(UnittestProto.repeatedInt32Extension));
+ }
+
+ public void testExtensionCopy() throws Exception {
+ TestAllExtensions original = TestUtil.getAllExtensionsSet();
+ TestAllExtensions copy = TestAllExtensions.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testExtensionMergeFrom() throws Exception {
+ TestAllExtensions original =
+ TestAllExtensions.newBuilder()
+ .setExtension(UnittestProto.optionalInt32Extension, 1).build();
+ TestAllExtensions merged =
+ TestAllExtensions.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestProto.optionalInt32Extension));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestProto.optionalInt32Extension));
+ }
+
+ // =================================================================
+ // Lite Extensions.
+
+ // We test lite extensions directly because they have a separate
+ // implementation from full extensions. In contrast, we do not test
+ // lite fields directly since they are implemented exactly the same as
+ // regular fields.
+
+ public void testLiteExtensionMessageOrBuilder() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtilLite.setAllExtensions(builder);
+ TestUtil.assertAllExtensionsSet(builder);
+
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertAllExtensionsSet(message);
+ }
+
+ public void testLiteExtensionRepeatedSetters() throws Exception {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ TestUtilLite.setAllExtensions(builder);
+ TestUtilLite.modifyRepeatedExtensions(builder);
+ TestUtil.assertRepeatedExtensionsModified(builder);
+
+ TestAllExtensionsLite message = builder.build();
+ TestUtil.assertRepeatedExtensionsModified(message);
+ }
+
+ public void testLiteExtensionDefaults() throws Exception {
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.getDefaultInstance());
+ TestUtil.assertExtensionsClear(TestAllExtensionsLite.newBuilder().build());
+ }
+
+ public void testClearLiteExtension() throws Exception {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ assertFalse(
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.optionalInt32ExtensionLite)
+ .hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(0,
+ TestAllExtensionsLite.newBuilder()
+ .addExtension(UnittestLite.repeatedInt32ExtensionLite, 1)
+ .clearExtension(UnittestLite.repeatedInt32ExtensionLite)
+ .getExtensionCount(UnittestLite.repeatedInt32ExtensionLite));
+ }
+
+ public void testLiteExtensionCopy() throws Exception {
+ TestAllExtensionsLite original = TestUtilLite.getAllLiteExtensionsSet();
+ TestAllExtensionsLite copy =
+ TestAllExtensionsLite.newBuilder(original).build();
+ TestUtil.assertAllExtensionsSet(copy);
+ }
+
+ public void testLiteExtensionMergeFrom() throws Exception {
+ TestAllExtensionsLite original =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 1).build();
+ TestAllExtensionsLite merged =
+ TestAllExtensionsLite.newBuilder().mergeFrom(original).build();
+ assertTrue(merged.hasExtension(UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) merged.getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ // =================================================================
+ // multiple_files_test
+
+ // Test that custom options of an file level enum are properly initialized.
+ // This test needs to be put before any other access to MultipleFilesTestProto
+ // or messages defined in multiple_files_test.proto because the class loading
+ // order affects initialization process of custom options.
+ public void testEnumValueOptionsInMultipleFilesMode() throws Exception {
+ assertEquals(12345, EnumWithNoOuter.FOO.getValueDescriptor().getOptions()
+ .getExtension(MultipleFilesTestProto.enumValueOption).intValue());
+ }
+
+ public void testMultipleFilesOption() throws Exception {
+ // We mostly just want to check that things compile.
+ MessageWithNoOuter message =
+ MessageWithNoOuter.newBuilder()
+ .setNested(MessageWithNoOuter.NestedMessage.newBuilder().setI(1))
+ .addForeign(TestAllTypes.newBuilder().setOptionalInt32(1))
+ .setNestedEnum(MessageWithNoOuter.NestedEnum.BAZ)
+ .setForeignEnum(EnumWithNoOuter.BAR)
+ .build();
+ assertEquals(message, MessageWithNoOuter.parseFrom(message.toByteString()));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ MessageWithNoOuter.getDescriptor().getFile());
+
+ Descriptors.FieldDescriptor field =
+ MessageWithNoOuter.getDescriptor().findFieldByName("foreign_enum");
+ assertEquals(EnumWithNoOuter.BAR.getValueDescriptor(),
+ message.getField(field));
+
+ assertEquals(MultipleFilesTestProto.getDescriptor(),
+ ServiceWithNoOuter.getDescriptor().getFile());
+
+ assertFalse(
+ TestAllExtensions.getDefaultInstance().hasExtension(
+ MultipleFilesTestProto.extensionWithOuter));
+ }
+
+ public void testOptionalFieldWithRequiredSubfieldsOptimizedForSize()
+ throws Exception {
+ TestOptionalOptimizedForSize message =
+ TestOptionalOptimizedForSize.getDefaultInstance();
+ assertTrue(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().buildPartial()
+ ).buildPartial();
+ assertFalse(message.isInitialized());
+
+ message = TestOptionalOptimizedForSize.newBuilder().setO(
+ TestRequiredOptimizedForSize.newBuilder().setX(5).buildPartial()
+ ).buildPartial();
+ assertTrue(message.isInitialized());
+ }
+
+ public void testUninitializedExtensionInOptimizedForSize()
+ throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().buildPartial());
+ assertFalse(builder.isInitialized());
+ assertFalse(builder.buildPartial().isInitialized());
+
+ builder = TestOptimizedForSize.newBuilder();
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(10).buildPartial());
+ assertTrue(builder.isInitialized());
+ assertTrue(builder.buildPartial().isInitialized());
+ }
+
+ public void testToBuilder() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes message = builder.build();
+ TestUtil.assertAllFieldsSet(message);
+ TestUtil.assertAllFieldsSet(message.toBuilder().build());
+ }
+
+ public void testFieldConstantValues() throws Exception {
+ assertEquals(TestAllTypes.NestedMessage.BB_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER, 1);
+ assertEquals(TestAllTypes.OPTIONALGROUP_FIELD_NUMBER, 16);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_MESSAGE_FIELD_NUMBER, 18);
+ assertEquals(TestAllTypes.OPTIONAL_NESTED_ENUM_FIELD_NUMBER, 21);
+ assertEquals(TestAllTypes.REPEATED_INT32_FIELD_NUMBER, 31);
+ assertEquals(TestAllTypes.REPEATEDGROUP_FIELD_NUMBER, 46);
+ assertEquals(TestAllTypes.REPEATED_NESTED_MESSAGE_FIELD_NUMBER, 48);
+ assertEquals(TestAllTypes.REPEATED_NESTED_ENUM_FIELD_NUMBER, 51);
+ }
+
+ public void testExtensionConstantValues() throws Exception {
+ assertEquals(UnittestProto.TestRequired.SINGLE_FIELD_NUMBER, 1000);
+ assertEquals(UnittestProto.TestRequired.MULTI_FIELD_NUMBER, 1001);
+ assertEquals(UnittestProto.OPTIONAL_INT32_EXTENSION_FIELD_NUMBER, 1);
+ assertEquals(UnittestProto.OPTIONALGROUP_EXTENSION_FIELD_NUMBER, 16);
+ assertEquals(
+ UnittestProto.OPTIONAL_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 18);
+ assertEquals(UnittestProto.OPTIONAL_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 21);
+ assertEquals(UnittestProto.REPEATED_INT32_EXTENSION_FIELD_NUMBER, 31);
+ assertEquals(UnittestProto.REPEATEDGROUP_EXTENSION_FIELD_NUMBER, 46);
+ assertEquals(
+ UnittestProto.REPEATED_NESTED_MESSAGE_EXTENSION_FIELD_NUMBER, 48);
+ assertEquals(UnittestProto.REPEATED_NESTED_ENUM_EXTENSION_FIELD_NUMBER, 51);
+ }
+
+ public void testRecursiveMessageDefaultInstance() throws Exception {
+ UnittestProto.TestRecursiveMessage message =
+ UnittestProto.TestRecursiveMessage.getDefaultInstance();
+ assertTrue(message != null);
+ assertNotNull(message.getA());
+ assertTrue(message.getA() == message);
+ }
+
+ public void testSerialize() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestUtil.setAllFields(builder);
+ TestAllTypes expected = builder.build();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testSerializePartial() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes expected = builder.buildPartial();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+ try {
+ out.writeObject(expected);
+ } finally {
+ out.close();
+ }
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ TestAllTypes actual = (TestAllTypes) in.readObject();
+ assertEquals(expected, actual);
+ }
+
+ public void testEnumValues() {
+ assertEquals(
+ TestAllTypes.NestedEnum.BAR.getNumber(),
+ TestAllTypes.NestedEnum.BAR_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.BAZ.getNumber(),
+ TestAllTypes.NestedEnum.BAZ_VALUE);
+ assertEquals(
+ TestAllTypes.NestedEnum.FOO.getNumber(),
+ TestAllTypes.NestedEnum.FOO_VALUE);
+ }
+
+ public void testNonNestedExtensionInitialization() {
+ assertTrue(NonNestedExtension.nonNestedExtension
+ .getMessageDefaultInstance() instanceof MyNonNestedExtension);
+ assertEquals("nonNestedExtension",
+ NonNestedExtension.nonNestedExtension.getDescriptor().getName());
+ }
+
+ public void testNestedExtensionInitialization() {
+ assertTrue(MyNestedExtension.recursiveExtension.getMessageDefaultInstance()
+ instanceof MessageToBeExtended);
+ assertEquals("recursiveExtension",
+ MyNestedExtension.recursiveExtension.getDescriptor().getName());
+ }
+
+ public void testNonNestedExtensionLiteInitialization() {
+ assertTrue(NonNestedExtensionLite.nonNestedExtensionLite
+ .getMessageDefaultInstance() instanceof MyNonNestedExtensionLite);
+ }
+
+ public void testNestedExtensionLiteInitialization() {
+ assertTrue(MyNestedExtensionLite.recursiveExtensionLite
+ .getMessageDefaultInstance() instanceof MessageLiteToBeExtended);
+ }
+
+ public void testInvalidations() throws Exception {
+ GeneratedMessage.enableAlwaysUseFieldBuildersForTesting();
+ TestAllTypes.NestedMessage nestedMessage1 =
+ TestAllTypes.NestedMessage.newBuilder().build();
+ TestAllTypes.NestedMessage nestedMessage2 =
+ TestAllTypes.NestedMessage.newBuilder().build();
+
+ // Set all three flavors (enum, primitive, message and singular/repeated)
+ // and verify no invalidations fired
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+ TestAllTypes.Builder builder = (TestAllTypes.Builder)
+ ((AbstractMessage) TestAllTypes.getDefaultInstance()).
+ newBuilderForType(mockParent);
+ builder.setOptionalInt32(1);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ builder.setOptionalNestedMessage(nestedMessage1);
+ builder.addRepeatedInt32(1);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAR);
+ builder.addRepeatedNestedMessage(nestedMessage1);
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ // Now tell it we want changes and make sure it's only fired once
+ // And do this for each flavor
+
+ // primitive single
+ builder.buildPartial();
+ builder.setOptionalInt32(2);
+ builder.setOptionalInt32(3);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ // enum single
+ builder.buildPartial();
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ builder.setOptionalNestedEnum(TestAllTypes.NestedEnum.BAR);
+ assertEquals(2, mockParent.getInvalidationCount());
+
+ // message single
+ builder.buildPartial();
+ builder.setOptionalNestedMessage(nestedMessage2);
+ builder.setOptionalNestedMessage(nestedMessage1);
+ assertEquals(3, mockParent.getInvalidationCount());
+
+ // primitive repeated
+ builder.buildPartial();
+ builder.addRepeatedInt32(2);
+ builder.addRepeatedInt32(3);
+ assertEquals(4, mockParent.getInvalidationCount());
+
+ // enum repeated
+ builder.buildPartial();
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+ assertEquals(5, mockParent.getInvalidationCount());
+
+ // message repeated
+ builder.buildPartial();
+ builder.addRepeatedNestedMessage(nestedMessage2);
+ builder.addRepeatedNestedMessage(nestedMessage1);
+ assertEquals(6, mockParent.getInvalidationCount());
+
+ }
+
+ public void testInvalidations_Extensions() throws Exception {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+
+ TestAllExtensions.Builder builder = (TestAllExtensions.Builder)
+ ((AbstractMessage) TestAllExtensions.getDefaultInstance()).
+ newBuilderForType(mockParent);
+
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 1);
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 2);
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ // Now tell it we want changes and make sure it's only fired once
+ builder.buildPartial();
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 2);
+ builder.addExtension(UnittestProto.repeatedInt32Extension, 3);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ builder.buildPartial();
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 0, 4);
+ builder.setExtension(UnittestProto.repeatedInt32Extension, 1, 5);
+ assertEquals(2, mockParent.getInvalidationCount());
+
+ builder.buildPartial();
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ builder.clearExtension(UnittestProto.repeatedInt32Extension);
+ assertEquals(3, mockParent.getInvalidationCount());
+ }
+
+ public void testBaseMessageOrBuilder() {
+ // Mostly just makes sure the base interface exists and has some methods.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes message = builder.buildPartial();
+ TestAllTypesOrBuilder builderAsInterface = (TestAllTypesOrBuilder) builder;
+ TestAllTypesOrBuilder messageAsInterface = (TestAllTypesOrBuilder) message;
+
+ assertEquals(
+ messageAsInterface.getDefaultBool(),
+ messageAsInterface.getDefaultBool());
+ assertEquals(
+ messageAsInterface.getOptionalDouble(),
+ messageAsInterface.getOptionalDouble());
+ }
+
+ public void testMessageOrBuilderGetters() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ // single fields
+ assertSame(ForeignMessage.getDefaultInstance(),
+ builder.getOptionalForeignMessageOrBuilder());
+ ForeignMessage.Builder subBuilder =
+ builder.getOptionalForeignMessageBuilder();
+ assertSame(subBuilder, builder.getOptionalForeignMessageOrBuilder());
+
+ // repeated fields
+ ForeignMessage m0 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m1 = ForeignMessage.newBuilder().buildPartial();
+ ForeignMessage m2 = ForeignMessage.newBuilder().buildPartial();
+ builder.addRepeatedForeignMessage(m0);
+ builder.addRepeatedForeignMessage(m1);
+ builder.addRepeatedForeignMessage(m2);
+ assertSame(m0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(m1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+ ForeignMessage.Builder b0 = builder.getRepeatedForeignMessageBuilder(0);
+ ForeignMessage.Builder b1 = builder.getRepeatedForeignMessageBuilder(1);
+ assertSame(b0, builder.getRepeatedForeignMessageOrBuilder(0));
+ assertSame(b1, builder.getRepeatedForeignMessageOrBuilder(1));
+ assertSame(m2, builder.getRepeatedForeignMessageOrBuilder(2));
+
+ List<? extends ForeignMessageOrBuilder> messageOrBuilderList =
+ builder.getRepeatedForeignMessageOrBuilderList();
+ assertSame(b0, messageOrBuilderList.get(0));
+ assertSame(b1, messageOrBuilderList.get(1));
+ assertSame(m2, messageOrBuilderList.get(2));
+ }
+
+ public void testGetFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("optional_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("optional_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(fieldDescriptor)
+ .mergeFrom((Message) builder1.getField(fieldDescriptor));
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.setField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.setField(foreignFieldDescriptor, foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder1.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.setField(importFieldDescriptor, importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder2 = builder2.getFieldBuilder(fieldDescriptor);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+ builder2.setField(fieldDescriptor, fieldBuilder2.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(foreignFieldDescriptor));
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.setField(foreignFieldDescriptor, foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor)
+ .mergeFrom((Message) builder2.getField(importFieldDescriptor));
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.setField(importFieldDescriptor, importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("optional_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.getOptionalNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getFieldBuilder(fieldDescriptor);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("optional_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(descriptor.findFieldByName("repeated_int32"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_message"));
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
+
+ // Test that when the default outer class name conflicts with another type
+ // defined in the proto the compiler will append a suffix to avoid the
+ // conflict.
+ public void testConflictingOuterClassName() {
+ // We just need to make sure we can refer to the outer class with the
+ // expected name. There is nothing else to test.
+ OuterClassNameTestOuterClass.OuterClassNameTest message =
+ OuterClassNameTestOuterClass.OuterClassNameTest.newBuilder().build();
+ assertTrue(message.getDescriptorForType() ==
+ OuterClassNameTestOuterClass.OuterClassNameTest.getDescriptor());
+
+ OuterClassNameTest2OuterClass.TestMessage2.NestedMessage.OuterClassNameTest2
+ message2 = OuterClassNameTest2OuterClass.TestMessage2.NestedMessage
+ .OuterClassNameTest2.newBuilder().build();
+ assertEquals(0, message2.getSerializedSize());
+
+ OuterClassNameTest3OuterClass.TestMessage3.NestedMessage.OuterClassNameTest3
+ enumValue = OuterClassNameTest3OuterClass.TestMessage3.NestedMessage
+ .OuterClassNameTest3.DUMMY_VALUE;
+ assertEquals(1, enumValue.getNumber());
+ }
+
+ // =================================================================
+ // oneof generated code test
+ public void testOneofEnumCase() throws Exception {
+ TestOneof2 message = TestOneof2.newBuilder()
+ .setFooInt(123).setFooString("foo").setFooCord("bar").build();
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+ }
+
+ public void testClearOneof() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder().setFooInt(123);
+ assertEquals(TestOneof2.FooCase.FOO_INT, builder.getFooCase());
+ builder.clearFoo();
+ assertEquals(TestOneof2.FooCase.FOO_NOT_SET, builder.getFooCase());
+ }
+
+ public void testSetOneofClearsOthers() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message =
+ builder.setFooInt(123).setFooString("foo").buildPartial();
+ assertTrue(message.hasFooString());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooCord("bar").buildPartial();
+ assertTrue(message.hasFooCord());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooStringPiece("baz").buildPartial();
+ assertTrue(message.hasFooStringPiece());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooBytes(TestUtil.toBytes("qux")).buildPartial();
+ assertTrue(message.hasFooBytes());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooEnum(TestOneof2.NestedEnum.FOO).buildPartial();
+ assertTrue(message.hasFooEnum());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).buildPartial();
+ assertTrue(message.hasFooMessage());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+
+ message = builder.setFooInt(123).buildPartial();
+ assertTrue(message.hasFooInt());
+ TestUtil.assertAtMostOneFieldSetOneof(message);
+ }
+
+ public void testOneofTypes() throws Exception {
+ // Primitive
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooInt(), 0);
+ assertFalse(builder.hasFooInt());
+ assertTrue(builder.setFooInt(123).hasFooInt());
+ assertEquals(builder.getFooInt(), 123);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooInt());
+ assertEquals(message.getFooInt(), 123);
+
+ assertFalse(builder.clearFooInt().hasFooInt());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 0);
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO);
+ assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum());
+ assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooEnum());
+ assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR);
+
+ assertFalse(builder.clearFooEnum().hasFooEnum());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooString(), "");
+ builder.setFooString("foo");
+ assertTrue(builder.hasFooString());
+ assertEquals(builder.getFooString(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooString());
+ assertEquals(message.getFooString(), "foo");
+ assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooString().hasFooString());
+ TestOneof2 message2 = builder.buildPartial();
+ assertFalse(message2.hasFooString());
+ assertEquals(message2.getFooString(), "");
+ assertEquals(message2.getFooStringBytes(), TestUtil.toBytes(""));
+
+ // Get method should not change the oneof value.
+ builder.setFooInt(123);
+ assertEquals(builder.getFooString(), "");
+ assertEquals(builder.getFooStringBytes(), TestUtil.toBytes(""));
+ assertEquals(123, builder.getFooInt());
+
+ message = builder.build();
+ assertEquals(message.getFooString(), "");
+ assertEquals(message.getFooStringBytes(), TestUtil.toBytes(""));
+ assertEquals(123, message.getFooInt());
+ }
+
+ // Cord
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooCord(), "");
+ builder.setFooCord("foo");
+ assertTrue(builder.hasFooCord());
+ assertEquals(builder.getFooCord(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooCord());
+ assertEquals(message.getFooCord(), "foo");
+ assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooCord().hasFooCord());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooCord());
+ assertEquals(message2.getFooCord(), "");
+ assertEquals(message2.getFooCordBytes(), TestUtil.toBytes(""));
+ }
+
+ // StringPiece
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooStringPiece(), "");
+ builder.setFooStringPiece("foo");
+ assertTrue(builder.hasFooStringPiece());
+ assertEquals(builder.getFooStringPiece(), "foo");
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooStringPiece());
+ assertEquals(message.getFooStringPiece(), "foo");
+ assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo"));
+
+ assertFalse(builder.clearFooStringPiece().hasFooStringPiece());
+ TestOneof2 message2 = builder.build();
+ assertFalse(message2.hasFooStringPiece());
+ assertEquals(message2.getFooStringPiece(), "");
+ assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes(""));
+ }
+
+ // Message
+ {
+ // set
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ assertEquals(builder.getFooMessage().getQuxInt(), 0);
+ builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
+ assertTrue(builder.hasFooMessage());
+ assertEquals(builder.getFooMessage().getQuxInt(), 234);
+ TestOneof2 message = builder.buildPartial();
+ assertTrue(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 234);
+
+ // clear
+ assertFalse(builder.clearFooMessage().hasFooString());
+ message = builder.build();
+ assertFalse(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 0);
+
+ // nested builder
+ builder = TestOneof2.newBuilder();
+ assertSame(builder.getFooMessageOrBuilder(),
+ TestOneof2.NestedMessage.getDefaultInstance());
+ assertFalse(builder.hasFooMessage());
+ builder.getFooMessageBuilder().setQuxInt(123);
+ assertTrue(builder.hasFooMessage());
+ assertEquals(builder.getFooMessage().getQuxInt(), 123);
+ message = builder.build();
+ assertTrue(message.hasFooMessage());
+ assertEquals(message.getFooMessage().getQuxInt(), 123);
+ }
+
+ // LazyMessage is tested in LazyMessageLiteTest.java
+ }
+
+ public void testOneofMerge() throws Exception {
+ // Primitive Type
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooInt(123).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 123);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooString("foo").build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooString());
+ assertEquals(message2.getFooString(), "foo");
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ }
+
+ // Message
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+ TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
+ assertTrue(message2.hasFooMessage());
+ assertEquals(message2.getFooMessage().getQuxInt(), 234);
+ }
+ }
+
+ public void testOneofSerialization() throws Exception {
+ // Primitive Type
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooInt(123).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooInt());
+ assertEquals(message2.getFooInt(), 123);
+ }
+
+ // String
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooString("foo").build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooString());
+ assertEquals(message2.getFooString(), "foo");
+ }
+
+ // Enum
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooEnum());
+ assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+ }
+
+ // Message
+ {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestOneof2 message = builder.setFooMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
+ ByteString serialized = message.toByteString();
+ TestOneof2 message2 = TestOneof2.parseFrom(serialized);
+ assertTrue(message2.hasFooMessage());
+ assertEquals(message2.getFooMessage().getQuxInt(), 234);
+ }
+ }
+
+ public void testOneofNestedBuilderOnChangePropagation() {
+ NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder();
+ TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder();
+ builder.getOneofNestedMessageBuilder();
+ assertTrue(builder.hasOneofNestedMessage());
+ assertTrue(parentBuilder.hasPayload());
+ NestedTestAllTypes message = parentBuilder.build();
+ assertTrue(message.hasPayload());
+ assertTrue(message.getPayload().hasOneofNestedMessage());
+ }
+
+ public void testGetRepeatedFieldBuilder() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+ FieldDescriptor foreignFieldDescriptor =
+ descriptor.findFieldByName("repeated_foreign_message");
+ FieldDescriptor importFieldDescriptor =
+ descriptor.findFieldByName("repeated_import_message");
+
+ // Mutate the message with new field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder1 = TestAllTypes.newBuilder();
+ Message.Builder fieldBuilder1 = builder1.newBuilderForField(
+ fieldDescriptor);
+ FieldDescriptor subFieldDescriptor1 =
+ fieldBuilder1.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder1.setField(subFieldDescriptor1, 1);
+ builder1.addRepeatedField(fieldDescriptor, fieldBuilder1.build());
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder1 = builder1.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor1 =
+ foreignFieldBuilder1.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder1.setField(subForeignFieldDescriptor1, 2);
+ builder1.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder1.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder1 = builder1.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor1 =
+ importFieldBuilder1.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder1.setField(subImportFieldDescriptor1, 3);
+ builder1.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder1.build());
+
+ Message newMessage1 = builder1.build();
+
+ // Mutate the message with existing field builder
+ // Mutate nested message
+ TestAllTypes.Builder builder2 = TestAllTypes.newBuilder();
+ builder2.addRepeatedNestedMessageBuilder();
+ Message.Builder fieldBuilder2 = builder2.getRepeatedFieldBuilder(
+ fieldDescriptor, 0);
+ FieldDescriptor subFieldDescriptor2 =
+ fieldBuilder2.getDescriptorForType().findFieldByName("bb");
+ fieldBuilder2.setField(subFieldDescriptor2, 1);
+
+ // Mutate foreign message
+ Message.Builder foreignFieldBuilder2 = builder2.newBuilderForField(
+ foreignFieldDescriptor);
+ FieldDescriptor subForeignFieldDescriptor2 =
+ foreignFieldBuilder2.getDescriptorForType().findFieldByName("c");
+ foreignFieldBuilder2.setField(subForeignFieldDescriptor2, 2);
+ builder2.addRepeatedField(foreignFieldDescriptor,
+ foreignFieldBuilder2.build());
+
+ // Mutate import message
+ Message.Builder importFieldBuilder2 = builder2.newBuilderForField(
+ importFieldDescriptor);
+ FieldDescriptor subImportFieldDescriptor2 =
+ importFieldBuilder2.getDescriptorForType().findFieldByName("d");
+ importFieldBuilder2.setField(subImportFieldDescriptor2, 3);
+ builder2.addRepeatedField(importFieldDescriptor,
+ importFieldBuilder2.build());
+
+ Message newMessage2 = builder2.build();
+
+ // These two messages should be equal.
+ assertEquals(newMessage1, newMessage2);
+ }
+
+ public void testGetRepeatedFieldBuilderWithInitializedValue() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor fieldDescriptor =
+ descriptor.findFieldByName("repeated_nested_message");
+
+ // Before setting field, builder is initialized by default value.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.addRepeatedNestedMessageBuilder();
+ NestedMessage.Builder fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ assertEquals(0, fieldBuilder.getBb());
+
+ // Setting field value with new field builder instance.
+ builder = TestAllTypes.newBuilder();
+ NestedMessage.Builder newFieldBuilder =
+ builder.addRepeatedNestedMessageBuilder();
+ newFieldBuilder.setBb(2);
+ // Then get the field builder instance by getRepeatedFieldBuilder().
+ fieldBuilder =
+ (NestedMessage.Builder) builder.getRepeatedFieldBuilder(fieldDescriptor, 0);
+ // It should contain new value.
+ assertEquals(2, fieldBuilder.getBb());
+ // These two builder should be equal.
+ assertSame(fieldBuilder, newFieldBuilder);
+ }
+
+ public void testGetRepeatedFieldBuilderNotSupportedException() {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("repeated_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("repeated_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(descriptor.findFieldByName("optional_int32"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_enum"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.getRepeatedFieldBuilder(
+ descriptor.findFieldByName("optional_nested_message"), 0);
+ fail("Exception was not thrown");
+ } catch (UnsupportedOperationException e) {
+ // We expect this exception.
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
new file mode 100644
index 0000000000..60c85450c3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IntArrayListTest.java
@@ -0,0 +1,461 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link IntArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class IntArrayListTest extends TestCase {
+
+ private static final IntArrayList UNARY_LIST =
+ newImmutableIntArrayList(1);
+ private static final IntArrayList TERTIARY_LIST =
+ newImmutableIntArrayList(1, 2, 3);
+
+ private IntArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new IntArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(IntArrayList.emptyList(), IntArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(IntArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addInt(3);
+ list.addInt(4);
+ list.addInt(5);
+ list.addInt(7);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+ list.set(0, 1);
+ assertEquals(2, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1, (int) TERTIARY_LIST.get(0));
+ assertEquals(2, (int) TERTIARY_LIST.get(1));
+ assertEquals(3, (int) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetInt() {
+ assertEquals(1, TERTIARY_LIST.getInt(0));
+ assertEquals(2, TERTIARY_LIST.getInt(1));
+ assertEquals(3, TERTIARY_LIST.getInt(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, IntArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addInt(3);
+ list.addInt(4);
+ list.addInt(6);
+ list.addInt(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(17);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addInt(2);
+ list.addInt(4);
+
+ assertEquals(2, (int) list.set(0, 3));
+ assertEquals(3, list.getInt(0));
+
+ assertEquals(4, (int) list.set(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.set(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetInt() {
+ list.addInt(1);
+ list.addInt(3);
+
+ assertEquals(1, list.setInt(0, 0));
+ assertEquals(0, list.getInt(0));
+
+ assertEquals(3, list.setInt(1, 0));
+ assertEquals(0, list.getInt(1));
+
+ try {
+ list.setInt(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2));
+ assertEquals(asList(2), list);
+
+ assertTrue(list.add(3));
+ list.add(0, 4);
+ assertEquals(asList(4, 2, 3), list);
+
+ list.add(0, 1);
+ list.add(0, 0);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Integer.valueOf(5 + i));
+ }
+ assertEquals(
+ asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10),
+ list);
+
+ try {
+ list.add(-1, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddInt() {
+ assertEquals(0, list.size());
+
+ list.addInt(2);
+ assertEquals(asList(2), list);
+
+ list.addInt(3);
+ assertEquals(asList(2, 3), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1)));
+ assertEquals(1, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, list.getInt(0));
+
+ assertTrue(list.addAll(asList(2, 3, 4, 5, 6)));
+ assertEquals(asList(1, 2, 3, 4, 5, 6), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list);
+
+ assertFalse(list.addAll(Collections.<Integer>emptyList()));
+ assertFalse(list.addAll(IntArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1, (int) list.remove(0));
+ assertEquals(asList(2, 3), list);
+
+ assertTrue(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertFalse(list.remove(Integer.valueOf(3)));
+ assertEquals(asList(2), list);
+
+ assertEquals(2, (int) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(IntArrayList list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new IntArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addInt(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setInt(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static IntArrayList newImmutableIntArrayList(int... elements) {
+ IntArrayList list = new IntArrayList();
+ for (int element : elements) {
+ list.addInt(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
new file mode 100644
index 0000000000..756049b41f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java
@@ -0,0 +1,186 @@
+// 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 static com.google.protobuf.IsValidUtf8TestUtil.DIRECT_NIO_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT;
+import static com.google.protobuf.IsValidUtf8TestUtil.EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT;
+import static com.google.protobuf.IsValidUtf8TestUtil.HEAP_NIO_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.LITERAL_FACTORY;
+import static com.google.protobuf.IsValidUtf8TestUtil.testBytes;
+
+import com.google.protobuf.IsValidUtf8TestUtil.ByteStringFactory;
+import com.google.protobuf.IsValidUtf8TestUtil.Shard;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests cases for {@link ByteString#isValidUtf8()}. This includes three
+ * brute force tests that actually test every permutation of one byte, two byte,
+ * and three byte sequences to ensure that the method produces the right result
+ * for every possible byte encoding where "right" means it's consistent with
+ * java's UTF-8 string encoding/decoding such that the method returns true for
+ * any sequence that will round trip when converted to a String and then back to
+ * bytes and will return false for any sequence that will not round trip.
+ * See also {@link IsValidUtf8FourByteTest}. It also includes some
+ * other more targeted tests.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+public class IsValidUtf8Test extends TestCase {
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_1Byte() {
+ testBytes(LITERAL_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(HEAP_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(DIRECT_NIO_FACTORY, 1, EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all two byte permutations work.
+ */
+ public void testIsValidUtf8_2Bytes() {
+ testBytes(LITERAL_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(HEAP_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(DIRECT_NIO_FACTORY, 2, IsValidUtf8TestUtil.EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+
+ /**
+ * Tests that round tripping of all three byte permutations work.
+ */
+ public void testIsValidUtf8_3Bytes() {
+ // Travis' OOM killer doesn't like this test
+ if (System.getenv("TRAVIS") == null) {
+ testBytes(LITERAL_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(HEAP_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+ testBytes(DIRECT_NIO_FACTORY, 3, EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT);
+ }
+ }
+
+ /**
+ * Tests that round tripping of a sample of four byte permutations work.
+ * All permutations are prohibitively expensive to test for automated runs;
+ * {@link IsValidUtf8FourByteTest} is used for full coverage. This method
+ * tests specific four-byte cases.
+ */
+ public void testIsValidUtf8_4BytesSamples() {
+ // Valid 4 byte.
+ assertValidUtf8(0xF0, 0xA4, 0xAD, 0xA2);
+
+ // Bad trailing bytes
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0x7F);
+ assertInvalidUtf8(0xF0, 0xA4, 0xAD, 0xC0);
+
+ // Special cases for byte2
+ assertInvalidUtf8(0xF0, 0x8F, 0xAD, 0xA2);
+ assertInvalidUtf8(0xF4, 0x90, 0xAD, 0xA2);
+ }
+
+ /**
+ * Tests some hard-coded test cases.
+ */
+ public void testSomeSequences() {
+ // Empty
+ assertTrue(asBytes("").isValidUtf8());
+
+ // One-byte characters, including control characters
+ assertTrue(asBytes("\u0000abc\u007f").isValidUtf8());
+
+ // Two-byte characters
+ assertTrue(asBytes("\u00a2\u00a2").isValidUtf8());
+
+ // Three-byte characters
+ assertTrue(asBytes("\u020ac\u020ac").isValidUtf8());
+
+ // Four-byte characters
+ assertTrue(asBytes("\u024B62\u024B62").isValidUtf8());
+
+ // Mixed string
+ assertTrue(asBytes("a\u020ac\u00a2b\\u024B62u020acc\u00a2de\u024B62").isValidUtf8());
+
+ // Not a valid string
+ assertInvalidUtf8(-1, 0, -1, 0);
+ }
+
+ private byte[] toByteArray(int... bytes) {
+ byte[] realBytes = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ realBytes[i] = (byte) bytes[i];
+ }
+ return realBytes;
+ }
+
+ private void assertValidUtf8(ByteStringFactory factory, int[] bytes, boolean not) {
+ byte[] realBytes = toByteArray(bytes);
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes));
+ assertTrue(not ^ Utf8.isValidUtf8(realBytes, 0, bytes.length));
+ ByteString leaf = factory.newByteString(realBytes);
+ ByteString sub = leaf.substring(0, bytes.length);
+ assertTrue(not ^ leaf.isValidUtf8());
+ assertTrue(not ^ sub.isValidUtf8());
+ ByteString[] ropes = {
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, leaf),
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, sub),
+ RopeByteString.newInstanceForTest(leaf, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, ByteString.EMPTY),
+ RopeByteString.newInstanceForTest(sub, leaf)};
+ for (ByteString rope : ropes) {
+ assertTrue(not ^ rope.isValidUtf8());
+ }
+ }
+
+ private void assertValidUtf8(int... bytes) {
+ assertValidUtf8(LITERAL_FACTORY, bytes, false);
+ assertValidUtf8(HEAP_NIO_FACTORY, bytes, false);
+ assertValidUtf8(DIRECT_NIO_FACTORY, bytes, false);
+ }
+
+ private void assertInvalidUtf8(int... bytes) {
+ assertValidUtf8(LITERAL_FACTORY, bytes, true);
+ assertValidUtf8(HEAP_NIO_FACTORY, bytes, true);
+ assertValidUtf8(DIRECT_NIO_FACTORY, bytes, true);
+ }
+
+ private static ByteString asBytes(String s) {
+ return ByteString.copyFromUtf8(s);
+ }
+
+ public void testShardsHaveExpectedRoundTrippables() {
+ // A sanity check.
+ int actual = 0;
+ for (Shard shard : IsValidUtf8TestUtil.FOUR_BYTE_SHARDS) {
+ actual += shard.expected;
+ }
+ assertEquals(IsValidUtf8TestUtil.EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT, actual);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
new file mode 100644
index 0000000000..16a808bf31
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java
@@ -0,0 +1,448 @@
+// 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.ref.SoftReference;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.logging.Logger;
+
+/**
+ * Shared testing code for {@link IsValidUtf8Test} and
+ * {@link IsValidUtf8FourByteTest}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ * @author martinrb@google.com (Martin Buchholz)
+ */
+final class IsValidUtf8TestUtil {
+ private static Logger logger = Logger.getLogger(IsValidUtf8TestUtil.class.getName());
+
+ private IsValidUtf8TestUtil() {}
+
+ static interface ByteStringFactory {
+ ByteString newByteString(byte[] bytes);
+ }
+
+ static final ByteStringFactory LITERAL_FACTORY = new ByteStringFactory() {
+ @Override
+ public ByteString newByteString(byte[] bytes) {
+ return ByteString.wrap(bytes);
+ }
+ };
+
+ static final ByteStringFactory HEAP_NIO_FACTORY = new ByteStringFactory() {
+ @Override
+ public ByteString newByteString(byte[] bytes) {
+ return new NioByteString(ByteBuffer.wrap(bytes));
+ }
+ };
+
+ private static ThreadLocal<SoftReference<ByteBuffer>> directBuffer =
+ new ThreadLocal<SoftReference<ByteBuffer>>();
+
+ /**
+ * Factory for direct {@link ByteBuffer} instances. To reduce direct memory usage, this
+ * uses a thread local direct buffer. This means that each call will overwrite the buffer's
+ * contents from the previous call, so the calling code must be careful not to continue using
+ * a buffer returned from a previous invocation.
+ */
+ static final ByteStringFactory DIRECT_NIO_FACTORY = new ByteStringFactory() {
+ @Override
+ public ByteString newByteString(byte[] bytes) {
+ SoftReference<ByteBuffer> ref = directBuffer.get();
+ ByteBuffer buffer = ref == null ? null : ref.get();
+ if (buffer == null || buffer.capacity() < bytes.length) {
+ buffer = ByteBuffer.allocateDirect(bytes.length);
+ directBuffer.set(new SoftReference<ByteBuffer>(buffer));
+ }
+ buffer.clear();
+ buffer.put(bytes);
+ buffer.flip();
+ return new NioByteString(buffer);
+ }
+ };
+
+ // 128 - [chars 0x0000 to 0x007f]
+ static final long ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x007f - 0x0000 + 1;
+
+ // 128
+ static final long EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT = ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1920 [chars 0x0080 to 0x07FF]
+ static final long TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x07FF - 0x0080 + 1;
+
+ // 18,304
+ static final long EXPECTED_TWO_BYTE_ROUNDTRIPPABLE_COUNT =
+ // Both bytes are one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 2) +
+ // The possible number of two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 2048
+ static final long THREE_BYTE_SURROGATES = 2 * 1024;
+
+ // 61,440 [chars 0x0800 to 0xFFFF, minus surrogates]
+ static final long THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS =
+ 0xFFFF - 0x0800 + 1 - THREE_BYTE_SURROGATES;
+
+ // 2,650,112
+ static final long EXPECTED_THREE_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 3) +
+ // One two byte character and a one byte character
+ 2 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Three byte characters
+ THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ // 1,048,576 [chars 0x10000L to 0x10FFFF]
+ static final long FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS = 0x10FFFF - 0x10000L + 1;
+
+ // 289,571,839
+ static final long EXPECTED_FOUR_BYTE_ROUNDTRIPPABLE_COUNT =
+ // All one byte characters
+ (long) Math.pow(EXPECTED_ONE_BYTE_ROUNDTRIPPABLE_COUNT, 4) +
+ // One and three byte characters
+ 2 * THREE_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Two two byte characters
+ TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS +
+ // Permutations of one and two byte characters
+ 3 * TWO_BYTE_ROUNDTRIPPABLE_CHARACTERS * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS
+ * ONE_BYTE_ROUNDTRIPPABLE_CHARACTERS
+ +
+ // Four byte characters
+ FOUR_BYTE_ROUNDTRIPPABLE_CHARACTERS;
+
+ static final class Shard {
+ final long index;
+ final long start;
+ final long lim;
+ final long expected;
+
+
+ public Shard(long index, long start, long lim, long expected) {
+ assertTrue(start < lim);
+ this.index = index;
+ this.start = start;
+ this.lim = lim;
+ this.expected = expected;
+ }
+ }
+
+ static final long[] FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES =
+ generateFourByteShardsExpectedRunnables();
+
+ private static long[] generateFourByteShardsExpectedRunnables() {
+ long[] expected = new long[128];
+
+ // 0-63 are all 5300224
+ for (int i = 0; i <= 63; i++) {
+ expected[i] = 5300224;
+ }
+
+ // 97-111 are all 2342912
+ for (int i = 97; i <= 111; i++) {
+ expected[i] = 2342912;
+ }
+
+ // 113-117 are all 1048576
+ for (int i = 113; i <= 117; i++) {
+ expected[i] = 1048576;
+ }
+
+ // One offs
+ expected[112] = 786432;
+ expected[118] = 786432;
+ expected[119] = 1048576;
+ expected[120] = 458752;
+ expected[121] = 524288;
+ expected[122] = 65536;
+
+ // Anything not assigned was the default 0.
+ return expected;
+ }
+
+ static final List<Shard> FOUR_BYTE_SHARDS =
+ generateFourByteShards(128, FOUR_BYTE_SHARDS_EXPECTED_ROUNTRIPPABLES);
+
+
+ private static List<Shard> generateFourByteShards(int numShards, long[] expected) {
+ assertEquals(numShards, expected.length);
+ List<Shard> shards = new ArrayList<Shard>(numShards);
+ long LIM = 1L << 32;
+ long increment = LIM / numShards;
+ assertTrue(LIM % numShards == 0);
+ for (int i = 0; i < numShards; i++) {
+ shards.add(new Shard(i, increment * i, increment * (i + 1), expected[i]));
+ }
+ return shards;
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified.
+ *
+ * @param factory the factory for {@link ByteString} instances.
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ */
+ static void testBytes(ByteStringFactory factory, int numBytes, long expectedCount) {
+ testBytes(factory, numBytes, expectedCount, 0, -1);
+ }
+
+ /**
+ * Helper to run the loop to test all the permutations for the number of bytes
+ * specified. This overload is useful for debugging to get the loop to start
+ * at a certain character.
+ *
+ * @param factory the factory for {@link ByteString} instances.
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ static void testBytes(
+ ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) {
+ Random rnd = new Random();
+ byte[] bytes = new byte[numBytes];
+
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < numBytes; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ ByteString bs = factory.newByteString(bytes);
+ boolean isRoundTrippable = bs.isValidUtf8();
+ String s = new String(bytes, Internal.UTF_8);
+ byte[] bytesReencoded = s.getBytes(Internal.UTF_8);
+ boolean bytesEqual = Arrays.equals(bytes, bytesReencoded);
+
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+
+ // Check agreement with static Utf8 methods.
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes));
+ assertEquals(isRoundTrippable, Utf8.isValidUtf8(bytes, 0, numBytes));
+
+ // Test partial sequences.
+ // Partition numBytes into three segments (not necessarily non-empty).
+ int i = rnd.nextInt(numBytes);
+ int j = rnd.nextInt(numBytes);
+ if (j < i) {
+ int tmp = i;
+ i = j;
+ j = tmp;
+ }
+ int state1 = Utf8.partialIsValidUtf8(Utf8.COMPLETE, bytes, 0, i);
+ int state2 = Utf8.partialIsValidUtf8(state1, bytes, i, j);
+ int state3 = Utf8.partialIsValidUtf8(state2, bytes, j, numBytes);
+ if (isRoundTrippable != (state3 == Utf8.COMPLETE)) {
+ System.out.printf("state=%04x %04x %04x i=%d j=%d%n", state1, state2, state3, i, j);
+ outputFailure(byteChar, bytes, bytesReencoded);
+ }
+ assertEquals(isRoundTrippable, (state3 == Utf8.COMPLETE));
+
+ // Test ropes built out of small partial sequences
+ ByteString rope = RopeByteString.newInstanceForTest(
+ bs.substring(0, i),
+ RopeByteString.newInstanceForTest(bs.substring(i, j), bs.substring(j, numBytes)));
+ assertSame(RopeByteString.class, rope.getClass());
+
+ ByteString[] byteStrings = {bs, bs.substring(0, numBytes), rope};
+ for (ByteString x : byteStrings) {
+ assertEquals(isRoundTrippable, x.isValidUtf8());
+ assertEquals(state3, x.partialIsValidUtf8(Utf8.COMPLETE, 0, numBytes));
+
+ assertEquals(state1, x.partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state1, x.substring(0, i).partialIsValidUtf8(Utf8.COMPLETE, 0, i));
+ assertEquals(state2, x.partialIsValidUtf8(state1, i, j - i));
+ assertEquals(state2, x.substring(i, j).partialIsValidUtf8(state1, 0, j - i));
+ assertEquals(state3, x.partialIsValidUtf8(state2, j, numBytes - j));
+ assertEquals(state3, x.substring(j, numBytes).partialIsValidUtf8(state2, 0, numBytes - j));
+ }
+
+ // ByteString reduplication should not affect its UTF-8 validity.
+ ByteString ropeADope = RopeByteString.newInstanceForTest(bs, bs.substring(0, numBytes));
+ assertEquals(isRoundTrippable, ropeADope.isValidUtf8());
+
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ count++;
+ if (byteChar != 0 && byteChar % 1000000L == 0) {
+ logger.info("Processed " + (byteChar / 1000000L) + " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ /**
+ * Variation of {@link #testBytes} that does less allocation using the
+ * low-level encoders/decoders directly. Checked in because it's useful for
+ * debugging when trying to process bytes faster, but since it doesn't use the
+ * actual String class, it's possible for incompatibilities to develop
+ * (although unlikely).
+ *
+ * @param factory the factory for {@link ByteString} instances.
+ * @param numBytes the number of bytes in the byte array
+ * @param expectedCount the expected number of roundtrippable permutations
+ * @param start the starting bytes encoded as a long as big-endian
+ * @param lim the limit of bytes to process encoded as a long as big-endian,
+ * or -1 to mean the max limit for numBytes
+ */
+ static void testBytesUsingByteBuffers(
+ ByteStringFactory factory, int numBytes, long expectedCount, long start, long lim) {
+ CharsetDecoder decoder =
+ Internal.UTF_8.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ CharsetEncoder encoder =
+ Internal.UTF_8.newEncoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE);
+ byte[] bytes = new byte[numBytes];
+ int maxChars = (int) (decoder.maxCharsPerByte() * numBytes) + 1;
+ char[] charsDecoded = new char[(int) (decoder.maxCharsPerByte() * numBytes) + 1];
+ int maxBytes = (int) (encoder.maxBytesPerChar() * maxChars) + 1;
+ byte[] bytesReencoded = new byte[maxBytes];
+
+ ByteBuffer bb = ByteBuffer.wrap(bytes);
+ CharBuffer cb = CharBuffer.wrap(charsDecoded);
+ ByteBuffer bbReencoded = ByteBuffer.wrap(bytesReencoded);
+ if (lim == -1) {
+ lim = 1L << (numBytes * 8);
+ }
+ long count = 0;
+ long countRoundTripped = 0;
+ for (long byteChar = start; byteChar < lim; byteChar++) {
+ bb.rewind();
+ bb.limit(bytes.length);
+ cb.rewind();
+ cb.limit(charsDecoded.length);
+ bbReencoded.rewind();
+ bbReencoded.limit(bytesReencoded.length);
+ encoder.reset();
+ decoder.reset();
+ long tmpByteChar = byteChar;
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[bytes.length - i - 1] = (byte) tmpByteChar;
+ tmpByteChar = tmpByteChar >> 8;
+ }
+ boolean isRoundTrippable = factory.newByteString(bytes).isValidUtf8();
+ CoderResult result = decoder.decode(bb, cb, true);
+ assertFalse(result.isError());
+ result = decoder.flush(cb);
+ assertFalse(result.isError());
+
+ int charLen = cb.position();
+ cb.rewind();
+ cb.limit(charLen);
+ result = encoder.encode(cb, bbReencoded, true);
+ assertFalse(result.isError());
+ result = encoder.flush(bbReencoded);
+ assertFalse(result.isError());
+
+ boolean bytesEqual = true;
+ int bytesLen = bbReencoded.position();
+ if (bytesLen != numBytes) {
+ bytesEqual = false;
+ } else {
+ for (int i = 0; i < numBytes; i++) {
+ if (bytes[i] != bytesReencoded[i]) {
+ bytesEqual = false;
+ break;
+ }
+ }
+ }
+ if (bytesEqual != isRoundTrippable) {
+ outputFailure(byteChar, bytes, bytesReencoded, bytesLen);
+ }
+
+ count++;
+ if (isRoundTrippable) {
+ countRoundTripped++;
+ }
+ if (byteChar != 0 && byteChar % 1000000 == 0) {
+ logger.info("Processed " + (byteChar / 1000000) + " million characters");
+ }
+ }
+ logger.info("Round tripped " + countRoundTripped + " of " + count);
+ assertEquals(expectedCount, countRoundTripped);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after) {
+ outputFailure(byteChar, bytes, after, after.length);
+ }
+
+ private static void outputFailure(long byteChar, byte[] bytes, byte[] after, int len) {
+ fail("Failure: (" + Long.toHexString(byteChar) + ") " + toHexString(bytes) + " => "
+ + toHexString(after, len));
+ }
+
+ private static String toHexString(byte[] b) {
+ return toHexString(b, b.length);
+ }
+
+ private static String toHexString(byte[] b, int len) {
+ StringBuilder s = new StringBuilder();
+ s.append("\"");
+ for (int i = 0; i < len; i++) {
+ if (i > 0) {
+ s.append(" ");
+ }
+ s.append(String.format("%02x", b[i] & 0xFF));
+ }
+ s.append("\"");
+ return s.toString();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
new file mode 100644
index 0000000000..813fe6bc69
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -0,0 +1,246 @@
+// 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 static protobuf_unittest.UnittestProto.optionalInt32Extension;
+
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link LazyFieldLite}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldLiteTest extends TestCase {
+
+ public void testGetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testGetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testSetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ message = lazyField.getValue(TestAllTypes.getDefaultInstance());
+ changeValue(lazyField);
+ assertEquals(message, lazyField.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testSetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ MessageLite value = lazyField.getValue(TestAllExtensions.getDefaultInstance());
+ changeValue(lazyField);
+ assertEquals(value, lazyField.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+ public void testGetSerializedSize() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+ changeValue(lazyField);
+ assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+ }
+
+ public void testGetSerializedSizeEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.getSerializedSize(), lazyField.getSerializedSize());
+ changeValue(lazyField);
+ assertNotEqual(message.getSerializedSize(), lazyField.getSerializedSize());
+ }
+
+ public void testGetByteString() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.toByteString(), lazyField.toByteString());
+ changeValue(lazyField);
+ assertNotEqual(message.toByteString(), lazyField.toByteString());
+ }
+
+ public void testGetByteStringEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite lazyField = createLazyFieldLiteFromMessage(message);
+ assertEquals(message.toByteString(), lazyField.toByteString());
+ changeValue(lazyField);
+ assertNotEqual(message.toByteString(), lazyField.toByteString());
+ }
+
+ public void testMergeExtensions() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyFieldLite original = createLazyFieldLiteFromMessage(message);
+ LazyFieldLite merged = new LazyFieldLite();
+ merged.merge(original);
+ TestAllExtensions value = (TestAllExtensions) merged.getValue(
+ TestAllExtensions.getDefaultInstance());
+ assertEquals(message, value);
+ }
+
+ public void testEmptyLazyField() throws Exception {
+ LazyFieldLite field = new LazyFieldLite();
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testInvalidProto() throws Exception {
+ // Silently fails and uses the default instance.
+ LazyFieldLite field = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ assertEquals(
+ TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance()));
+ assertEquals(0, field.getSerializedSize());
+ assertEquals(ByteString.EMPTY, field.toByteString());
+ }
+
+ public void testMergeBeforeParsing() throws Exception {
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1);
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+
+ field1.merge(field2);
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeOneNotParsed() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build();
+ TestAllTypes expected =
+ TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build();
+
+ LazyFieldLite field1 = LazyFieldLite.fromValue(message1);
+ field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2);
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+
+ // Now reverse which one is parsed first.
+ field1 = LazyFieldLite.fromValue(message1);
+ field2 = createLazyFieldLiteFromMessage(message2);
+ field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing.
+ field1.merge(field2);
+ assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeInvalid() throws Exception {
+ // Test a few different paths that involve one message that was not parsed.
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build();
+ LazyFieldLite valid = LazyFieldLite.fromValue(message);
+ LazyFieldLite invalid = new LazyFieldLite(
+ TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid"));
+ invalid.merge(valid);
+
+ // We swallow the exception and just use the set field.
+ assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance()));
+ }
+
+ public void testMergeKeepsExtensionsWhenPossible() throws Exception {
+ // In this test we attempt to only use the empty registry, which will strip out all extensions
+ // when serializing and then parsing. We verify that each code path will attempt to not
+ // serialize and parse a message that was set directly without going through the
+ // extensionRegistry.
+ TestAllExtensions messageWithExtensions =
+ TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build();
+ TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build();
+
+ ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry();
+
+ LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now reverse the order of the merging.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.merge(LazyFieldLite.fromValue(messageWithExtensions));
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // Now try parsing the empty field first.
+ field = LazyFieldLite.fromValue(messageWithExtensions);
+ LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+
+ // And again reverse.
+ field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage);
+ field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing.
+ other = LazyFieldLite.fromValue(messageWithExtensions);
+ field.merge(other);
+ assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance()));
+ }
+
+
+ // Help methods.
+
+ private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
+ return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message);
+ }
+
+ private LazyFieldLite createLazyFieldLiteFromMessage(
+ ExtensionRegistryLite extensionRegistry, MessageLite message) {
+ ByteString bytes = message.toByteString();
+ return new LazyFieldLite(extensionRegistry, bytes);
+ }
+
+ private void changeValue(LazyFieldLite lazyField) {
+ TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+ builder.addRepeatedBool(true);
+ MessageLite newMessage = builder.build();
+ lazyField.setValue(newMessage);
+ }
+
+ private void assertNotEqual(Object unexpected, Object actual) {
+ assertFalse(unexpected == actual
+ || (unexpected != null && unexpected.equals(actual)));
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
new file mode 100644
index 0000000000..5f013f3ce3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyFieldTest.java
@@ -0,0 +1,120 @@
+// 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 protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link LazyField}.
+ *
+ * @author xiangl@google.com (Xiang Li)
+ */
+public class LazyFieldTest extends TestCase {
+ public void testHashCode() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField =
+ createLazyFieldFromMessage(message);
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ lazyField.getValue();
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ changeValue(lazyField);
+ // make sure two messages have different hash code
+ assertNotEqual(message.hashCode(), lazyField.hashCode());
+ }
+
+ public void testHashCodeEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ lazyField.getValue();
+ assertEquals(message.hashCode(), lazyField.hashCode());
+ changeValue(lazyField);
+ // make sure two messages have different hash code
+ assertNotEqual(message.hashCode(), lazyField.hashCode());
+ }
+
+ public void testGetValue() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message, lazyField.getValue());
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue());
+ }
+
+ public void testGetValueEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertEquals(message, lazyField.getValue());
+ changeValue(lazyField);
+ assertNotEqual(message, lazyField.getValue());
+ }
+
+ public void testEqualsObject() {
+ MessageLite message = TestUtil.getAllSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertTrue(lazyField.equals(message));
+ changeValue(lazyField);
+ assertFalse(lazyField.equals(message));
+ assertFalse(message.equals(lazyField.getValue()));
+ }
+
+ public void testEqualsObjectEx() throws Exception {
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ LazyField lazyField = createLazyFieldFromMessage(message);
+ assertTrue(lazyField.equals(message));
+ changeValue(lazyField);
+ assertFalse(lazyField.equals(message));
+ assertFalse(message.equals(lazyField.getValue()));
+ }
+
+ // Help methods.
+
+ private LazyField createLazyFieldFromMessage(MessageLite message) {
+ ByteString bytes = message.toByteString();
+ return new LazyField(message.getDefaultInstanceForType(),
+ TestUtil.getExtensionRegistry(), bytes);
+ }
+
+ private void changeValue(LazyField lazyField) {
+ TestAllTypes.Builder builder = TestUtil.getAllSet().toBuilder();
+ builder.addRepeatedBool(true);
+ MessageLite newMessage = builder.build();
+ lazyField.setValue(newMessage);
+ }
+
+ private void assertNotEqual(Object unexpected, Object actual) {
+ assertFalse(unexpected == actual
+ || (unexpected != null && unexpected.equals(actual)));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
new file mode 100644
index 0000000000..968ca2065c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java
@@ -0,0 +1,335 @@
+// 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 protobuf_unittest.LazyFieldsLite.LazyExtension;
+import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyMessageLite;
+import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for messages with lazy fields.
+ *
+ * @author niwasaki@google.com (Naoki Iwasaki)
+ */
+public class LazyMessageLiteTest extends TestCase {
+
+ private Parser<LazyInnerMessageLite> originalLazyInnerMessageLiteParser;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSetValues() {
+ LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+ .setNum(3)
+ .build();
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(2)
+ .setNested(nested)
+ .build();
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .setInner(inner)
+ .setOneofNum(123)
+ .setOneofInner(inner)
+ .build();
+
+ assertEquals(1, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+
+ assertEquals(2, outer.getInner().getNum());
+ assertEquals(42, outer.getInner().getNumWithDefault());
+
+ assertEquals(3, outer.getInner().getNested().getNum());
+ assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+ assertFalse(outer.hasOneofNum());
+ assertTrue(outer.hasOneofInner());
+
+ assertEquals(2, outer.getOneofInner().getNum());
+ assertEquals(42, outer.getOneofInner().getNumWithDefault());
+ assertEquals(3, outer.getOneofInner().getNested().getNum());
+ assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+ }
+
+ public void testSetRepeatedValues() {
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+ .build();
+
+ assertEquals(1, outer.getNum());
+ assertEquals(2, outer.getRepeatedInnerCount());
+ assertEquals(119, outer.getRepeatedInner(0).getNum());
+ assertEquals(122, outer.getRepeatedInner(1).getNum());
+ }
+
+ public void testRepeatedMutability() throws Exception {
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+ .build();
+
+ outer = LazyMessageLite.parseFrom(outer.toByteArray());
+ try {
+ outer.getRepeatedInnerList().set(1, null);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ public void testAddAll() {
+ ArrayList<LazyInnerMessageLite> inners = new ArrayList<LazyInnerMessageLite>();
+ int count = 4;
+ for (int i = 0; i < count; i++) {
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(i)
+ .build();
+ inners.add(inner);
+ }
+
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .addAllRepeatedInner(inners)
+ .build();
+ assertEquals(count, outer.getRepeatedInnerCount());
+ for (int i = 0; i < count; i++) {
+ assertEquals(i, outer.getRepeatedInner(i).getNum());
+ }
+ }
+
+ public void testGetDefaultValues() {
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .build();
+
+ assertEquals(0, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+
+ assertEquals(0, outer.getInner().getNum());
+ assertEquals(42, outer.getInner().getNumWithDefault());
+
+ assertEquals(0, outer.getInner().getNested().getNum());
+ assertEquals(4, outer.getInner().getNested().getNumWithDefault());
+
+ assertEquals(0, outer.getOneofNum());
+
+ assertEquals(0, outer.getOneofInner().getNum());
+ assertEquals(42, outer.getOneofInner().getNumWithDefault());
+ assertEquals(0, outer.getOneofInner().getNested().getNum());
+ assertEquals(4, outer.getOneofInner().getNested().getNumWithDefault());
+ }
+
+ public void testClearValues() {
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+
+ LazyMessageLite.Builder outerBuilder = LazyMessageLite.newBuilder();
+
+ assertEquals(0, outerBuilder.build().getNum());
+
+
+ // Set/Clear num
+ outerBuilder.setNum(100);
+
+ assertEquals(100, outerBuilder.build().getNum());
+ assertEquals(421, outerBuilder.build().getNumWithDefault());
+ assertFalse(outerBuilder.build().hasInner());
+
+ outerBuilder.clearNum();
+
+ assertEquals(0, outerBuilder.build().getNum());
+ assertEquals(421, outerBuilder.build().getNumWithDefault());
+ assertFalse(outerBuilder.build().hasInner());
+
+
+ // Set/Clear all
+ outerBuilder.setNum(100)
+ .setInner(inner)
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(119))
+ .addRepeatedInner(LazyInnerMessageLite.newBuilder().setNum(122))
+ .setOneofInner(LazyInnerMessageLite.newBuilder().setNum(123));
+
+ LazyMessageLite outer = outerBuilder.build();
+ assertEquals(100, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+ assertTrue(outer.hasInner());
+ assertEquals(115, outer.getInner().getNum());
+ assertEquals(2, outer.getRepeatedInnerCount());
+ assertEquals(119, outer.getRepeatedInner(0).getNum());
+ assertEquals(122, outer.getRepeatedInner(1).getNum());
+ assertTrue(outer.hasOneofInner());
+ assertEquals(123, outer.getOneofInner().getNum());
+
+ outerBuilder.clear();
+
+ outer = outerBuilder.build();
+
+ assertEquals(0, outer.getNum());
+ assertEquals(421, outer.getNumWithDefault());
+ assertFalse(outer.hasInner());
+ assertEquals(0, outer.getRepeatedInnerCount());
+ assertFalse(outer.hasOneofInner());
+ assertEquals(0, outer.getOneofInner().getNum());
+ }
+
+ public void testMergeValues() {
+ LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+ .setNumWithDefault(122)
+ .build();
+
+ LazyInnerMessageLite innerMerging = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+ LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+ .setNum(119)
+ .setInner(innerMerging)
+ .setOneofInner(innerMerging)
+ .build();
+
+ LazyMessageLite merged = LazyMessageLite
+ .newBuilder(outerBase)
+ .mergeFrom(outerMerging)
+ .build();
+ assertEquals(119, merged.getNum());
+ assertEquals(122, merged.getNumWithDefault());
+ assertEquals(115, merged.getInner().getNum());
+ assertEquals(42, merged.getInner().getNumWithDefault());
+ assertEquals(115, merged.getOneofInner().getNum());
+ assertEquals(42, merged.getOneofInner().getNumWithDefault());
+ }
+
+ public void testMergeDefaultValues() {
+ LazyInnerMessageLite innerBase = LazyInnerMessageLite.newBuilder()
+ .setNum(115)
+ .build();
+ LazyMessageLite outerBase = LazyMessageLite.newBuilder()
+ .setNum(119)
+ .setNumWithDefault(122)
+ .setInner(innerBase)
+ .setOneofInner(innerBase)
+ .build();
+
+ LazyMessageLite outerMerging = LazyMessageLite.newBuilder()
+ .build();
+
+ LazyMessageLite merged = LazyMessageLite
+ .newBuilder(outerBase)
+ .mergeFrom(outerMerging)
+ .build();
+ // Merging default-instance shouldn't overwrite values in the base message.
+ assertEquals(119, merged.getNum());
+ assertEquals(122, merged.getNumWithDefault());
+ assertEquals(115, merged.getInner().getNum());
+ assertEquals(42, merged.getInner().getNumWithDefault());
+ assertEquals(115, merged.getOneofInner().getNum());
+ assertEquals(42, merged.getOneofInner().getNumWithDefault());
+ }
+
+ // Regression test for b/28198805.
+ public void testMergeOneofMessages() throws Exception {
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder().build();
+ LazyMessageLite outer = LazyMessageLite.newBuilder().setOneofInner(inner).build();
+ ByteString data1 = outer.toByteString();
+
+ // The following should not alter the content of the 'outer' message.
+ LazyMessageLite.Builder merged = LazyMessageLite.newBuilder().mergeFrom(outer);
+ LazyInnerMessageLite anotherInner = LazyInnerMessageLite.newBuilder().setNum(12345).build();
+ merged.setOneofInner(anotherInner);
+
+ // Check that the 'outer' stays the same.
+ ByteString data2 = outer.toByteString();
+ assertEquals(data1, data2);
+ assertEquals(0, outer.getOneofInner().getNum());
+ }
+
+ public void testSerialize() throws InvalidProtocolBufferException {
+ LazyNestedInnerMessageLite nested = LazyNestedInnerMessageLite.newBuilder()
+ .setNum(3)
+ .build();
+ LazyInnerMessageLite inner = LazyInnerMessageLite.newBuilder()
+ .setNum(2)
+ .setNested(nested)
+ .build();
+ LazyMessageLite outer = LazyMessageLite.newBuilder()
+ .setNum(1)
+ .setInner(inner)
+ .setOneofInner(inner)
+ .build();
+
+ ByteString bytes = outer.toByteString();
+ assertEquals(bytes.size(), outer.getSerializedSize());
+
+ LazyMessageLite deserialized = LazyMessageLite.parseFrom(bytes);
+
+ assertEquals(1, deserialized.getNum());
+ assertEquals(421, deserialized.getNumWithDefault());
+
+ assertEquals(2, deserialized.getInner().getNum());
+ assertEquals(42, deserialized.getInner().getNumWithDefault());
+
+ assertEquals(3, deserialized.getInner().getNested().getNum());
+ assertEquals(4, deserialized.getInner().getNested().getNumWithDefault());
+
+ assertEquals(2, deserialized.getOneofInner().getNum());
+ assertEquals(42, deserialized.getOneofInner().getNumWithDefault());
+ assertEquals(3, deserialized.getOneofInner().getNested().getNum());
+ assertEquals(4, deserialized.getOneofInner().getNested().getNumWithDefault());
+
+ assertEquals(bytes, deserialized.toByteString());
+ }
+
+ public void testExtensions() throws Exception {
+ LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder();
+ innerBuilder.setExtension(
+ LazyExtension.extension, LazyExtension.newBuilder()
+ .setName("name").build());
+ assertTrue(innerBuilder.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName());
+
+ LazyInnerMessageLite innerMessage = innerBuilder.build();
+ assertTrue(innerMessage.hasExtension(LazyExtension.extension));
+ assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName());
+
+ LazyMessageLite lite = LazyMessageLite.newBuilder()
+ .setInner(innerMessage).build();
+ assertTrue(lite.getInner().hasExtension(LazyExtension.extension));
+ assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
new file mode 100644
index 0000000000..2fc3124d4c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java
@@ -0,0 +1,363 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link LazyStringArrayList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringArrayListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testJustStrings() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+
+ list.set(1, STRING_C);
+ assertSame(STRING_C, list.get(1));
+
+ list.remove(1);
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_C, list.get(1));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertEquals(BYTE_STRING_A, byteStringList.get(0));
+ assertEquals(BYTE_STRING_C, byteStringList.get(1));
+
+ // Underlying list should be transformed.
+ assertSame(byteStringList.get(0), list.getByteString(0));
+ assertSame(byteStringList.get(1), list.getByteString(1));
+ }
+
+ public void testJustByteString() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(BYTE_STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ assertEquals(3, list.size());
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_B, list.getByteString(1));
+ assertSame(BYTE_STRING_C, list.getByteString(2));
+
+ list.remove(1);
+ assertSame(BYTE_STRING_A, list.getByteString(0));
+ assertSame(BYTE_STRING_C, list.getByteString(1));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertSame(BYTE_STRING_A, byteStringList.get(0));
+ assertSame(BYTE_STRING_C, byteStringList.get(1));
+ }
+
+ public void testConversionBackAndForth() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(BYTE_STRING_B);
+ list.add(BYTE_STRING_C);
+
+ // String a should be the same because it was originally a string
+ assertSame(STRING_A, list.get(0));
+
+ // String b and c should be different because the string has to be computed
+ // from the ByteString
+ String bPrime = list.get(1);
+ assertNotSame(STRING_B, bPrime);
+ assertEquals(STRING_B, bPrime);
+ String cPrime = list.get(2);
+ assertNotSame(STRING_C, cPrime);
+ assertEquals(STRING_C, cPrime);
+
+ // String c and c should stay the same once cached.
+ assertSame(bPrime, list.get(1));
+ assertSame(cPrime, list.get(2));
+
+ // ByteString needs to be computed from string for both a and b
+ ByteString aPrimeByteString = list.getByteString(0);
+ assertEquals(BYTE_STRING_A, aPrimeByteString);
+ ByteString bPrimeByteString = list.getByteString(1);
+ assertNotSame(BYTE_STRING_B, bPrimeByteString);
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+
+ // Once cached, ByteString should stay cached.
+ assertSame(aPrimeByteString, list.getByteString(0));
+ assertSame(bPrimeByteString, list.getByteString(1));
+ }
+
+ public void testCopyConstructorCopiesByReference() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testListCopyConstructor() {
+ List<String> list1 = new ArrayList<String>();
+ list1.add(STRING_A);
+ list1.add(STRING_B);
+ list1.add(STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList(list1);
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(STRING_B, list2.get(1));
+ assertSame(STRING_C, list2.get(2));
+ }
+
+ public void testAddAllCopiesByReferenceIfPossible() {
+ LazyStringArrayList list1 = new LazyStringArrayList();
+ list1.add(STRING_A);
+ list1.add(BYTE_STRING_B);
+ list1.add(BYTE_STRING_C);
+
+ LazyStringArrayList list2 = new LazyStringArrayList();
+ list2.addAll(list1);
+
+ assertEquals(3, list2.size());
+ assertSame(STRING_A, list2.get(0));
+ assertSame(BYTE_STRING_B, list2.getByteString(1));
+ assertSame(BYTE_STRING_C, list2.getByteString(2));
+ }
+
+ public void testModificationWithIteration() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.addAll(asList(STRING_A, STRING_B, STRING_C));
+ Iterator<String> iterator = list.iterator();
+ assertEquals(3, list.size());
+ assertEquals(STRING_A, list.get(0));
+ assertEquals(STRING_A, iterator.next());
+
+ // Does not structurally modify.
+ iterator = list.iterator();
+ list.set(0, STRING_B);
+ iterator.next();
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, STRING_C);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.add(STRING_B);
+ list.add(STRING_C);
+ list.makeImmutable();
+ assertGenericListImmutable(list, STRING_A);
+
+ // LazyStringArrayList has extra methods not covered in the generic
+ // assertion.
+
+ try {
+ list.add(BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteArray(Collections.singletonList(BYTE_STRING_A.toByteArray()));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAllByteString(asList(BYTE_STRING_A));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.mergeFrom(new LazyStringArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A.toByteArray());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testImmutabilityPropagation() {
+ LazyStringArrayList list = new LazyStringArrayList();
+ list.add(STRING_A);
+ list.makeImmutable();
+
+ assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A);
+
+ // Arrays use reference equality so need to retrieve the underlying value
+ // to properly test deep immutability.
+ List<byte[]> byteArrayList = list.asByteArrayList();
+ assertGenericListImmutable(byteArrayList, byteArrayList.get(0));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> void assertGenericListImmutable(List<T> list, T value) {
+ try {
+ list.add(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(asList(value));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(asList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
new file mode 100644
index 0000000000..006e493366
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java
@@ -0,0 +1,130 @@
+// 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 protobuf_unittest.UnittestProto;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Tests to make sure the lazy conversion of UTF8-encoded byte arrays to
+ * strings works correctly.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class LazyStringEndToEndTest extends TestCase {
+
+ private static ByteString TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8 =
+ ByteString.copyFrom(new byte[] {
+ 114, 4, -1, 0, -1, 0, -30, 2, 4, -1,
+ 0, -1, 0, -30, 2, 4, -1, 0, -1, 0, });
+
+ private ByteString encodedTestAllTypes;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.encodedTestAllTypes = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .addRepeatedString("baz")
+ .build()
+ .toByteString();
+ }
+
+ /**
+ * Tests that an invalid UTF8 string will roundtrip through a parse
+ * and serialization.
+ */
+ public void testParseAndSerialize() throws InvalidProtocolBufferException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ ByteString bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+
+ tV2.getOptionalString();
+ bytes = tV2.toByteString();
+ assertEquals(TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8, bytes);
+ }
+
+ public void testParseAndWrite() throws IOException {
+ UnittestProto.TestAllTypes tV2 = UnittestProto.TestAllTypes.parseFrom(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8);
+ byte[] sink = new byte[TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8.size()];
+ CodedOutputStream outputStream = CodedOutputStream.newInstance(sink);
+ tV2.writeTo(outputStream);
+ outputStream.flush();
+ assertEquals(
+ TEST_ALL_TYPES_SERIALIZED_WITH_ILLEGAL_UTF8,
+ ByteString.copyFrom(sink));
+ }
+
+ public void testCaching() {
+ String a = "a";
+ String b = "b";
+ String c = "c";
+ UnittestProto.TestAllTypes proto = UnittestProto.TestAllTypes.newBuilder()
+ .setOptionalString(a)
+ .addRepeatedString(b)
+ .addRepeatedString(c)
+ .build();
+
+ // String should be the one we passed it.
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
+
+
+ // Ensure serialization keeps strings cached.
+ proto.toByteString();
+
+ // And now the string should stay cached.
+ assertSame(a, proto.getOptionalString());
+ assertSame(b, proto.getRepeatedString(0));
+ assertSame(c, proto.getRepeatedString(1));
+ }
+
+ public void testNoStringCachingIfOnlyBytesAccessed() throws Exception {
+ UnittestProto.TestAllTypes proto =
+ UnittestProto.TestAllTypes.parseFrom(encodedTestAllTypes);
+ ByteString optional = proto.getOptionalStringBytes();
+ assertSame(optional, proto.getOptionalStringBytes());
+ assertSame(optional, proto.toBuilder().getOptionalStringBytes());
+
+ ByteString repeated0 = proto.getRepeatedStringBytes(0);
+ ByteString repeated1 = proto.getRepeatedStringBytes(1);
+ assertSame(repeated0, proto.getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.getRepeatedStringBytes(1));
+ assertSame(repeated0, proto.toBuilder().getRepeatedStringBytes(0));
+ assertSame(repeated1, proto.toBuilder().getRepeatedStringBytes(1));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
new file mode 100644
index 0000000000..4764ca1bbc
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
@@ -0,0 +1,125 @@
+// 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 protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
+
+import junit.framework.TestCase;
+
+/**
+ * Test generate equal and hash methods for the lite runtime.
+ *
+ * @author pbogle@google.com Phil Bogle
+ */
+public class LiteEqualsAndHashTest extends TestCase {
+
+ public void testEquals() throws Exception {
+ // Since the generated equals and hashCode methods for lite messages are a
+ // mostly complete subset of those for regular messages, we can mostly assume
+ // that the generated methods are already thoroughly tested by the regular tests.
+
+ // This test mostly just verifies is that a proto with
+ // optimize_for = LITE_RUNTIME and java_generates_equals_and_hash_compiles
+ // correctly when linked only against the lite library.
+
+ // We do however do some basic testing to make sure that equals is actually
+ // overridden to test for value equality rather than simple object equality.
+
+ // Check that two identical objs are equal.
+ Foo foo1a = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo1b = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo2 = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo2"))
+ .build();
+
+ // Check that equals is doing value rather than object equality.
+ assertEquals(foo1a, foo1b);
+ assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+ // Check that a diffeent object is not equal.
+ assertFalse(foo1a.equals(foo2));
+
+ // Check that two objects which have different types but the same field values are not
+ // considered to be equal.
+ Bar bar = Bar.newBuilder().setName("bar").build();
+ BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+ assertFalse(bar.equals(barPrime));
+ }
+
+ public void testOneofEquals() throws Exception {
+ TestOneofEquals.Builder builder = TestOneofEquals.newBuilder();
+ TestOneofEquals message1 = builder.build();
+ // Set message2's name field to default value. The two messages should be different when we
+ // check with the oneof case.
+ builder.setName("");
+ TestOneofEquals message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
+ public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+ Foo fooWithOnlyValue = Foo.newBuilder()
+ .setValue(1)
+ .build();
+
+ Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .build();
+
+ Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+ assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+ assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+ }
+
+ private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+ assertFalse(o1.equals(o2));
+ assertFalse(o1.hashCode() == o2.hashCode());
+ }
+
+ public void testRecursiveHashcode() {
+ // This tests that we don't infinite loop.
+ TestRecursiveOneof.getDefaultInstance().hashCode();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteTest.java
new file mode 100644
index 0000000000..538432f7c1
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteTest.java
@@ -0,0 +1,2273 @@
+// 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 static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup;
+import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite;
+import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
+import junit.framework.TestCase;
+
+/**
+ * Test lite runtime.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class LiteTest extends TestCase {
+ @Override
+ public void setUp() throws Exception {
+ // Test that nested extensions are initialized correctly even if the outer
+ // class has not been accessed directly. This was once a bug with lite
+ // messages.
+ //
+ // We put this in setUp() rather than in its own test method because we
+ // need to make sure it runs before any actual tests.
+ assertTrue(TestNestedExtensionLite.nestedExtension != null);
+ }
+
+ public void testLite() throws Exception {
+ // Since lite messages are a subset of regular messages, we can mostly
+ // assume that the functionality of lite messages is already thoroughly
+ // tested by the regular tests. All this test really verifies is that
+ // a proto with optimize_for = LITE_RUNTIME compiles correctly when
+ // linked only against the lite library. That is all tested at compile
+ // time, leaving not much to do in this method. Let's just do some random
+ // stuff to make sure the lite message is actually here and usable.
+
+ TestAllTypesLite message =
+ TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123)
+ .addRepeatedString("hello")
+ .setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .build();
+
+ ByteString data = message.toByteString();
+
+ TestAllTypesLite message2 = TestAllTypesLite.parseFrom(data);
+
+ assertEquals(123, message2.getOptionalInt32());
+ assertEquals(1, message2.getRepeatedStringCount());
+ assertEquals("hello", message2.getRepeatedString(0));
+ assertEquals(7, message2.getOptionalNestedMessage().getBb());
+ }
+
+ public void testLiteExtensions() throws Exception {
+ // TODO(kenton): Unlike other features of the lite library, extensions are
+ // implemented completely differently from the regular library. We
+ // should probably test them more thoroughly.
+
+ TestAllExtensionsLite message =
+ TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "hello")
+ .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+ TestAllTypesLite.NestedEnum.BAZ)
+ .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+ .build();
+
+ // Test copying a message, since coping extensions actually does use a
+ // different code path between lite and regular libraries, and as of this
+ // writing, parsing hasn't been implemented yet.
+ TestAllExtensionsLite message2 = message.toBuilder().build();
+
+ assertEquals(123, (int) message2.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(1, message2.getExtensionCount(
+ UnittestLite.repeatedStringExtensionLite));
+ assertEquals(1, message2.getExtension(
+ UnittestLite.repeatedStringExtensionLite).size());
+ assertEquals("hello", message2.getExtension(
+ UnittestLite.repeatedStringExtensionLite, 0));
+ assertEquals(TestAllTypesLite.NestedEnum.BAZ, message2.getExtension(
+ UnittestLite.optionalNestedEnumExtensionLite));
+ assertEquals(7, message2.getExtension(
+ UnittestLite.optionalNestedMessageExtensionLite).getBb());
+ }
+
+ public void testClone() {
+ TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder()
+ .setOptionalInt32(123);
+ assertEquals(
+ expected.getOptionalInt32(), expected.clone().getOptionalInt32());
+
+ TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123);
+ assertEquals(
+ expected2.getExtension(UnittestLite.optionalInt32ExtensionLite),
+ expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite));
+ }
+
+ public void testAddAll() {
+ try {
+ TestAllTypesLite.newBuilder()
+ .addAllRepeatedBytes(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+ TestAllTypesLite message = builder.build();
+ TestAllTypesLite messageAfterBuild;
+ builder.setOptionalBool(true);
+ assertEquals(false, message.getOptionalBool());
+ assertEquals(true, builder.getOptionalBool());
+ messageAfterBuild = builder.build();
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+ assertEquals(false, message.getOptionalBool());
+ builder.clearOptionalBool();
+ assertEquals(false, builder.getOptionalBool());
+ assertEquals(true, messageAfterBuild.getOptionalBool());
+
+ message = builder.build();
+ builder.setOptionalBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+ builder.clearOptionalBytes();
+ assertEquals(ByteString.EMPTY, builder.getOptionalBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes());
+
+ message = builder.build();
+ builder.setOptionalCord("hi");
+ assertEquals("", message.getOptionalCord());
+ assertEquals("hi", builder.getOptionalCord());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+ assertEquals("", message.getOptionalCord());
+ builder.clearOptionalCord();
+ assertEquals("", builder.getOptionalCord());
+ assertEquals("hi", messageAfterBuild.getOptionalCord());
+
+ message = builder.build();
+ builder.setOptionalCordBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalCordBytes());
+ builder.clearOptionalCord();
+ assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalCordBytes());
+
+ message = builder.build();
+ builder.setOptionalDouble(1);
+ assertEquals(0D, message.getOptionalDouble());
+ assertEquals(1D, builder.getOptionalDouble());
+ messageAfterBuild = builder.build();
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+ assertEquals(0D, message.getOptionalDouble());
+ builder.clearOptionalDouble();
+ assertEquals(0D, builder.getOptionalDouble());
+ assertEquals(1D, messageAfterBuild.getOptionalDouble());
+
+ message = builder.build();
+ builder.setOptionalFixed32(1);
+ assertEquals(0, message.getOptionalFixed32());
+ assertEquals(1, builder.getOptionalFixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+ assertEquals(0, message.getOptionalFixed32());
+ builder.clearOptionalFixed32();
+ assertEquals(0, builder.getOptionalFixed32());
+ assertEquals(1, messageAfterBuild.getOptionalFixed32());
+
+ message = builder.build();
+ builder.setOptionalFixed64(1);
+ assertEquals(0L, message.getOptionalFixed64());
+ assertEquals(1L, builder.getOptionalFixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+ assertEquals(0L, message.getOptionalFixed64());
+ builder.clearOptionalFixed64();
+ assertEquals(0L, builder.getOptionalFixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalFixed64());
+
+ message = builder.build();
+ builder.setOptionalFloat(1);
+ assertEquals(0F, message.getOptionalFloat());
+ assertEquals(1F, builder.getOptionalFloat());
+ messageAfterBuild = builder.build();
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+ assertEquals(0F, message.getOptionalFloat());
+ builder.clearOptionalFloat();
+ assertEquals(0F, builder.getOptionalFloat());
+ assertEquals(1F, messageAfterBuild.getOptionalFloat());
+
+ message = builder.build();
+ builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum());
+ builder.clearOptionalForeignEnum();
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum());
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getOptionalForeignEnum());
+
+ message = builder.build();
+ ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder()
+ .setC(1)
+ .build();
+ builder.setOptionalForeignMessage(foreignMessage);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ assertEquals(foreignMessage, builder.getOptionalForeignMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage());
+
+ message = builder.build();
+ ForeignMessageLite.Builder foreignMessageBuilder =
+ ForeignMessageLite.newBuilder()
+ .setC(3);
+ builder.setOptionalForeignMessage(foreignMessageBuilder);
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ assertEquals(foreignMessageBuilder.build(), builder.getOptionalForeignMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ message.getOptionalForeignMessage());
+ builder.clearOptionalForeignMessage();
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getOptionalForeignMessage());
+ assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getOptionalForeignMessage());
+
+ message = builder.build();
+ OptionalGroup optionalGroup = OptionalGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.setOptionalGroup(optionalGroup);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ assertEquals(optionalGroup, builder.getOptionalGroup());
+ messageAfterBuild = builder.build();
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup());
+
+ message = builder.build();
+ OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder()
+ .setA(3);
+ builder.setOptionalGroup(optionalGroupBuilder);
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ assertEquals(optionalGroupBuilder.build(), builder.getOptionalGroup());
+ messageAfterBuild = builder.build();
+ assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), message.getOptionalGroup());
+ builder.clearOptionalGroup();
+ assertEquals(
+ OptionalGroup.getDefaultInstance(), builder.getOptionalGroup());
+ assertEquals(optionalGroupBuilder.build(), messageAfterBuild.getOptionalGroup());
+
+ message = builder.build();
+ builder.setOptionalInt32(1);
+ assertEquals(0, message.getOptionalInt32());
+ assertEquals(1, builder.getOptionalInt32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+ assertEquals(0, message.getOptionalInt32());
+ builder.clearOptionalInt32();
+ assertEquals(0, builder.getOptionalInt32());
+ assertEquals(1, messageAfterBuild.getOptionalInt32());
+
+ message = builder.build();
+ builder.setOptionalInt64(1);
+ assertEquals(0L, message.getOptionalInt64());
+ assertEquals(1L, builder.getOptionalInt64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+ assertEquals(0L, message.getOptionalInt64());
+ builder.clearOptionalInt64();
+ assertEquals(0L, builder.getOptionalInt64());
+ assertEquals(1L, messageAfterBuild.getOptionalInt64());
+
+ message = builder.build();
+ NestedMessage nestedMessage = NestedMessage.newBuilder()
+ .setBb(1)
+ .build();
+ builder.setOptionalLazyMessage(nestedMessage);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ assertEquals(nestedMessage, builder.getOptionalLazyMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage());
+
+ message = builder.build();
+ NestedMessage.Builder nestedMessageBuilder =
+ NestedMessage.newBuilder()
+ .setBb(3);
+ builder.setOptionalLazyMessage(nestedMessageBuilder);
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ assertEquals(nestedMessageBuilder.build(), builder.getOptionalLazyMessage());
+ messageAfterBuild = builder.build();
+ assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
+ assertEquals(
+ NestedMessage.getDefaultInstance(),
+ message.getOptionalLazyMessage());
+ builder.clearOptionalLazyMessage();
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage());
+ assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getOptionalLazyMessage());
+
+ message = builder.build();
+ builder.setOptionalSfixed32(1);
+ assertEquals(0, message.getOptionalSfixed32());
+ assertEquals(1, builder.getOptionalSfixed32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+ assertEquals(0, message.getOptionalSfixed32());
+ builder.clearOptionalSfixed32();
+ assertEquals(0, builder.getOptionalSfixed32());
+ assertEquals(1, messageAfterBuild.getOptionalSfixed32());
+
+ message = builder.build();
+ builder.setOptionalSfixed64(1);
+ assertEquals(0L, message.getOptionalSfixed64());
+ assertEquals(1L, builder.getOptionalSfixed64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+ assertEquals(0L, message.getOptionalSfixed64());
+ builder.clearOptionalSfixed64();
+ assertEquals(0L, builder.getOptionalSfixed64());
+ assertEquals(1L, messageAfterBuild.getOptionalSfixed64());
+
+ message = builder.build();
+ builder.setOptionalSint32(1);
+ assertEquals(0, message.getOptionalSint32());
+ assertEquals(1, builder.getOptionalSint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+ builder.clearOptionalSint32();
+ assertEquals(0, builder.getOptionalSint32());
+ assertEquals(1, messageAfterBuild.getOptionalSint32());
+
+ message = builder.build();
+ builder.setOptionalSint64(1);
+ assertEquals(0L, message.getOptionalSint64());
+ assertEquals(1L, builder.getOptionalSint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+ assertEquals(0L, message.getOptionalSint64());
+ builder.clearOptionalSint64();
+ assertEquals(0L, builder.getOptionalSint64());
+ assertEquals(1L, messageAfterBuild.getOptionalSint64());
+
+ message = builder.build();
+ builder.setOptionalString("hi");
+ assertEquals("", message.getOptionalString());
+ assertEquals("hi", builder.getOptionalString());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+ assertEquals("", message.getOptionalString());
+ builder.clearOptionalString();
+ assertEquals("", builder.getOptionalString());
+ assertEquals("hi", messageAfterBuild.getOptionalString());
+
+ message = builder.build();
+ builder.setOptionalStringBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringBytes());
+ builder.clearOptionalString();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringBytes());
+
+ message = builder.build();
+ builder.setOptionalStringPiece("hi");
+ assertEquals("", message.getOptionalStringPiece());
+ assertEquals("hi", builder.getOptionalStringPiece());
+ messageAfterBuild = builder.build();
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+ assertEquals("", message.getOptionalStringPiece());
+ builder.clearOptionalStringPiece();
+ assertEquals("", builder.getOptionalStringPiece());
+ assertEquals("hi", messageAfterBuild.getOptionalStringPiece());
+
+ message = builder.build();
+ builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no"));
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+ assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes());
+ builder.clearOptionalStringPiece();
+ assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes());
+ assertEquals(
+ ByteString.copyFromUtf8("no"),
+ messageAfterBuild.getOptionalStringPieceBytes());
+
+ message = builder.build();
+ builder.setOptionalUint32(1);
+ assertEquals(0, message.getOptionalUint32());
+ assertEquals(1, builder.getOptionalUint32());
+ messageAfterBuild = builder.build();
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+ assertEquals(0, message.getOptionalUint32());
+ builder.clearOptionalUint32();
+ assertEquals(0, builder.getOptionalUint32());
+ assertEquals(1, messageAfterBuild.getOptionalUint32());
+
+ message = builder.build();
+ builder.setOptionalUint64(1);
+ assertEquals(0L, message.getOptionalUint64());
+ assertEquals(1L, builder.getOptionalUint64());
+ messageAfterBuild = builder.build();
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+ assertEquals(0L, message.getOptionalUint64());
+ builder.clearOptionalUint64();
+ assertEquals(0L, builder.getOptionalUint64());
+ assertEquals(1L, messageAfterBuild.getOptionalUint64());
+
+ message = builder.build();
+ builder.addAllRepeatedBool(singletonList(true));
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi")));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addAllRepeatedCord(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addAllRepeatedDouble(singletonList(1D));
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedFixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedFloat(singletonList(1F));
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignEnum(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR));
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addAllRepeatedForeignMessage(singletonList(foreignMessage));
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignMessage();
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedGroup(
+ singletonList(RepeatedGroup.getDefaultInstance()));
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedGroup();
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addAllRepeatedInt32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addAllRepeatedInt64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addAllRepeatedLazyMessage(singletonList(nestedMessage));
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedLazyMessage();
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSfixed64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedSint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addAllRepeatedString(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addAllRepeatedStringPiece(singletonList("hi"));
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addAllRepeatedUint32(singletonList(1));
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addAllRepeatedUint64(singletonList(1L));
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ assertEquals(singletonList(true), builder.getRepeatedBoolList());
+ assertEquals(emptyList(), message.getRepeatedBoolList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBool();
+ assertEquals(emptyList(), builder.getRepeatedBoolList());
+ assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList());
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ builder.getRepeatedBytesList());
+ assertEquals(emptyList(), message.getRepeatedBytesList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedBytes();
+ assertEquals(emptyList(), builder.getRepeatedBytesList());
+ assertEquals(
+ singletonList(ByteString.copyFromUtf8("hi")),
+ messageAfterBuild.getRepeatedBytesList());
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ assertEquals(singletonList("hi"), builder.getRepeatedCordList());
+ assertEquals(emptyList(), message.getRepeatedCordList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedCord();
+ assertEquals(emptyList(), builder.getRepeatedCordList());
+ assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList());
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), builder.getRepeatedDoubleList());
+ assertEquals(emptyList(), message.getRepeatedDoubleList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedDouble();
+ assertEquals(emptyList(), builder.getRepeatedDoubleList());
+ assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList());
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedFixed32List());
+ assertEquals(emptyList(), message.getRepeatedFixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed32();
+ assertEquals(emptyList(), builder.getRepeatedFixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List());
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedFixed64List());
+ assertEquals(emptyList(), message.getRepeatedFixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFixed64();
+ assertEquals(emptyList(), builder.getRepeatedFixed64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List());
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ assertEquals(singletonList(1F), builder.getRepeatedFloatList());
+ assertEquals(emptyList(), message.getRepeatedFloatList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedFloat();
+ assertEquals(emptyList(), builder.getRepeatedFloatList());
+ assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList());
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ builder.getRepeatedForeignEnumList());
+ assertEquals(emptyList(), message.getRepeatedForeignEnumList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedForeignEnum();
+ assertEquals(emptyList(), builder.getRepeatedForeignEnumList());
+ assertEquals(
+ singletonList(ForeignEnumLite.FOREIGN_LITE_BAR),
+ messageAfterBuild.getRepeatedForeignEnumList());
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage), builder.getRepeatedForeignMessageList());
+ assertEquals(emptyList(), message.getRepeatedForeignMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedForeignMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedForeignMessageList());
+ assertEquals(
+ singletonList(foreignMessage),
+ messageAfterBuild.getRepeatedForeignMessageList());
+
+ message = builder.build();
+ builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ builder.getRepeatedGroupList());
+ assertEquals(emptyList(), message.getRepeatedGroupList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedGroup(0);
+ assertEquals(emptyList(), builder.getRepeatedGroupList());
+ assertEquals(
+ singletonList(RepeatedGroup.getDefaultInstance()),
+ messageAfterBuild.getRepeatedGroupList());
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ assertEquals(singletonList(1), builder.getRepeatedInt32List());
+ assertEquals(emptyList(), message.getRepeatedInt32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt32();
+ assertEquals(emptyList(), builder.getRepeatedInt32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List());
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ assertEquals(singletonList(1L), builder.getRepeatedInt64List());
+ assertEquals(emptyList(), message.getRepeatedInt64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedInt64();
+ assertEquals(emptyList(), builder.getRepeatedInt64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List());
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage), builder.getRepeatedLazyMessageList());
+ assertEquals(emptyList(), message.getRepeatedLazyMessageList());
+ messageAfterBuild = builder.build();
+ builder.removeRepeatedLazyMessage(0);
+ assertEquals(emptyList(), builder.getRepeatedLazyMessageList());
+ assertEquals(
+ singletonList(nestedMessage),
+ messageAfterBuild.getRepeatedLazyMessageList());
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), builder.getRepeatedSfixed32List());
+ assertEquals(emptyList(), message.getRepeatedSfixed32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed32();
+ assertEquals(emptyList(), builder.getRepeatedSfixed32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List());
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSfixed64List());
+ assertEquals(emptyList(), message.getRepeatedSfixed64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSfixed64();
+ assertEquals(emptyList(), builder.getRepeatedSfixed64List());
+ assertEquals(
+ singletonList(1L), messageAfterBuild.getRepeatedSfixed64List());
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ assertEquals(singletonList(1), builder.getRepeatedSint32List());
+ assertEquals(emptyList(), message.getRepeatedSint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint32();
+ assertEquals(emptyList(), builder.getRepeatedSint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List());
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedSint64List());
+ assertEquals(emptyList(), message.getRepeatedSint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedSint64();
+ assertEquals(emptyList(), builder.getRepeatedSint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List());
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringList());
+ assertEquals(emptyList(), message.getRepeatedStringList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedString();
+ assertEquals(emptyList(), builder.getRepeatedStringList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringList());
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList());
+ assertEquals(emptyList(), message.getRepeatedStringPieceList());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedStringPiece();
+ assertEquals(emptyList(), builder.getRepeatedStringPieceList());
+ assertEquals(
+ singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList());
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ assertEquals(singletonList(1), builder.getRepeatedUint32List());
+ assertEquals(emptyList(), message.getRepeatedUint32List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint32();
+ assertEquals(emptyList(), builder.getRepeatedUint32List());
+ assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List());
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ assertEquals(singletonList(1L), builder.getRepeatedUint64List());
+ assertEquals(emptyList(), message.getRepeatedUint64List());
+ messageAfterBuild = builder.build();
+ builder.clearRepeatedUint64();
+ assertEquals(emptyList(), builder.getRepeatedUint64List());
+ assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List());
+
+ message = builder.build();
+ builder.addRepeatedBool(true);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBoolCount());
+ builder.setRepeatedBool(0, false);
+ assertEquals(true, messageAfterBuild.getRepeatedBool(0));
+ assertEquals(false, builder.getRepeatedBool(0));
+ builder.clearRepeatedBool();
+
+ message = builder.build();
+ builder.addRepeatedBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedBytesCount());
+ builder.setRepeatedBytes(0, ByteString.EMPTY);
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0));
+ builder.clearRepeatedBytes();
+
+ message = builder.build();
+ builder.addRepeatedCord("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedCord(0));
+ assertEquals("", builder.getRepeatedCord(0));
+ builder.clearRepeatedCord();
+ message = builder.build();
+
+ builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedCordCount());
+ builder.setRepeatedCord(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0));
+ builder.clearRepeatedCord();
+
+ message = builder.build();
+ builder.addRepeatedDouble(1D);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedDoubleCount());
+ builder.setRepeatedDouble(0, 0D);
+ assertEquals(1D, messageAfterBuild.getRepeatedDouble(0));
+ assertEquals(0D, builder.getRepeatedDouble(0));
+ builder.clearRepeatedDouble();
+
+ message = builder.build();
+ builder.addRepeatedFixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed32Count());
+ builder.setRepeatedFixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedFixed32(0));
+ assertEquals(0, builder.getRepeatedFixed32(0));
+ builder.clearRepeatedFixed32();
+
+ message = builder.build();
+ builder.addRepeatedFixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFixed64Count());
+ builder.setRepeatedFixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0));
+ assertEquals(0L, builder.getRepeatedFixed64(0));
+ builder.clearRepeatedFixed64();
+
+ message = builder.build();
+ builder.addRepeatedFloat(1F);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedFloatCount());
+ builder.setRepeatedFloat(0, 0F);
+ assertEquals(1F, messageAfterBuild.getRepeatedFloat(0));
+ assertEquals(0F, builder.getRepeatedFloat(0));
+ builder.clearRepeatedFloat();
+
+ message = builder.build();
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignEnumCount());
+ builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO);
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_BAR,
+ messageAfterBuild.getRepeatedForeignEnum(0));
+ assertEquals(
+ ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0));
+ builder.clearRepeatedForeignEnum();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(foreignMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(
+ 0, ForeignMessageLite.getDefaultInstance());
+ assertEquals(foreignMessageBuilder.build(), messageAfterBuild.getRepeatedForeignMessage(0));
+ assertEquals(
+ ForeignMessageLite.getDefaultInstance(),
+ builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ builder.addRepeatedForeignMessage(0, foreignMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedForeignMessageCount());
+ builder.setRepeatedForeignMessage(0, foreignMessageBuilder);
+ assertEquals(
+ foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0));
+ assertEquals(foreignMessageBuilder.build(), builder.getRepeatedForeignMessage(0));
+ builder.clearRepeatedForeignMessage();
+
+ message = builder.build();
+ RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder()
+ .setA(1)
+ .build();
+ builder.addRepeatedGroup(repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroup);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder()
+ .setA(3);
+ builder.addRepeatedGroup(repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedGroup(0, repeatedGroupBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedGroupCount());
+ builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance());
+ assertEquals(repeatedGroupBuilder.build(), messageAfterBuild.getRepeatedGroup(0));
+ assertEquals(
+ RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0));
+ builder.clearRepeatedGroup();
+
+ message = builder.build();
+ builder.addRepeatedInt32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedInt32Count());
+ builder.setRepeatedInt32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedInt32(0));
+ assertEquals(0, builder.getRepeatedInt32(0));
+ builder.clearRepeatedInt32();
+
+ message = builder.build();
+ builder.addRepeatedInt64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedInt64Count());
+ builder.setRepeatedInt64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedInt64(0));
+ assertEquals(0L, builder.getRepeatedInt64(0));
+ builder.clearRepeatedInt64();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessage);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedLazyMessage(0, nestedMessageBuilder);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedLazyMessageCount());
+ builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance());
+ assertEquals(nestedMessageBuilder.build(), messageAfterBuild.getRepeatedLazyMessage(0));
+ assertEquals(
+ NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0));
+ builder.clearRepeatedLazyMessage();
+
+ message = builder.build();
+ builder.addRepeatedSfixed32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSfixed32Count());
+ builder.setRepeatedSfixed32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0));
+ assertEquals(0, builder.getRepeatedSfixed32(0));
+ builder.clearRepeatedSfixed32();
+
+ message = builder.build();
+ builder.addRepeatedSfixed64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSfixed64Count());
+ builder.setRepeatedSfixed64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0));
+ assertEquals(0L, builder.getRepeatedSfixed64(0));
+ builder.clearRepeatedSfixed64();
+
+ message = builder.build();
+ builder.addRepeatedSint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedSint32Count());
+ builder.setRepeatedSint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedSint32(0));
+ assertEquals(0, builder.getRepeatedSint32(0));
+ builder.clearRepeatedSint32();
+
+ message = builder.build();
+ builder.addRepeatedSint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedSint64Count());
+ builder.setRepeatedSint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedSint64(0));
+ assertEquals(0L, builder.getRepeatedSint64(0));
+ builder.clearRepeatedSint64();
+
+ message = builder.build();
+ builder.addRepeatedString("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedString(0));
+ assertEquals("", builder.getRepeatedString(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringCount());
+ builder.setRepeatedString(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0));
+ builder.clearRepeatedString();
+
+ message = builder.build();
+ builder.addRepeatedStringPiece("hi");
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0));
+ assertEquals("", builder.getRepeatedStringPiece(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi"));
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedStringPieceCount());
+ builder.setRepeatedStringPiece(0, "");
+ assertEquals(
+ ByteString.copyFromUtf8("hi"),
+ messageAfterBuild.getRepeatedStringPieceBytes(0));
+ assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0));
+ builder.clearRepeatedStringPiece();
+
+ message = builder.build();
+ builder.addRepeatedUint32(1);
+ messageAfterBuild = builder.build();
+ assertEquals(0, message.getRepeatedUint32Count());
+ builder.setRepeatedUint32(0, 0);
+ assertEquals(1, messageAfterBuild.getRepeatedUint32(0));
+ assertEquals(0, builder.getRepeatedUint32(0));
+ builder.clearRepeatedUint32();
+
+ message = builder.build();
+ builder.addRepeatedUint64(1L);
+ messageAfterBuild = builder.build();
+ assertEquals(0L, message.getRepeatedUint64Count());
+ builder.setRepeatedUint64(0, 0L);
+ assertEquals(1L, messageAfterBuild.getRepeatedUint64(0));
+ assertEquals(0L, builder.getRepeatedUint64(0));
+ builder.clearRepeatedUint64();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clearOptionalBool();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeFrom(TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build());
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(true, builder.build().getOptionalBool());
+ builder.clear();
+ assertEquals(0, builder.build().getSerializedSize());
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalForeignMessage(foreignMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ foreignMessage.getC(),
+ builder.build().getOptionalForeignMessage().getC());
+ builder.clearOptionalForeignMessage();
+
+ message = builder.build();
+ assertEquals(0, message.getSerializedSize());
+ builder.mergeOptionalLazyMessage(nestedMessage);
+ assertEquals(0, message.getSerializedSize());
+ assertEquals(
+ nestedMessage.getBb(),
+ builder.build().getOptionalLazyMessage().getBb());
+ builder.clearOptionalLazyMessage();
+
+ message = builder.build();
+ builder.setOneofString("hi");
+ assertEquals(
+ OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase());
+ assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase());
+ assertEquals("hi", builder.getOneofString());
+ messageAfterBuild = builder.build();
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ builder.setOneofUint32(1);
+ assertEquals(
+ OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase());
+ assertEquals("hi", messageAfterBuild.getOneofString());
+ assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase());
+ assertEquals(1, builder.getOneofUint32());
+ TestAllTypesLiteOrBuilder messageOrBuilder = builder;
+ assertEquals(OneofFieldCase.ONEOF_UINT32, messageOrBuilder.getOneofFieldCase());
+
+ TestAllExtensionsLite.Builder extendableMessageBuilder =
+ TestAllExtensionsLite.newBuilder();
+ TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build();
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 1);
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 1, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessageBuilder.setExtension(
+ UnittestLite.optionalInt32ExtensionLite, 3);
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 1, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ extendableMessage = extendableMessageBuilder.build();
+ assertEquals(
+ 3, (int) extendableMessageBuilder.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ // No extension registry, so it should be in unknown fields.
+ extendableMessage =
+ TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray());
+ assertFalse(extendableMessage.hasExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+
+ extendableMessageBuilder = extendableMessage.toBuilder();
+ extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11)
+ .build());
+
+ extendableMessage = extendableMessageBuilder.build();
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ extendableMessage = TestAllExtensionsLite.parseFrom(
+ extendableMessage.toByteArray(), registry);
+
+ // The unknown field was preserved.
+ assertEquals(
+ 3, (int) extendableMessage.getExtension(
+ UnittestLite.optionalInt32ExtensionLite));
+ assertEquals(
+ 11, (int) extendableMessage.getExtension(
+ UnittestLite.optionalFixed32ExtensionLite));
+ }
+
+ public void testToStringDefaultInstance() throws Exception {
+ assertToStringEquals("", TestAllTypesLite.getDefaultInstance());
+ }
+
+ public void testToStringScalarFieldsSuffixedWithList() throws Exception {
+ assertToStringEquals("deceptively_named_list: 7", TestAllTypesLite.newBuilder()
+ .setDeceptivelyNamedList(7)
+ .build());
+ }
+
+ public void testToStringPrimitives() throws Exception {
+ TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalInt64(9223372036854775807L)
+ .build();
+ assertToStringEquals("optional_int32: 1\noptional_int64: 9223372036854775807", proto);
+
+ proto = TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .setOptionalNestedEnum(TestAllTypesLite.NestedEnum.BAZ)
+ .build();
+ assertToStringEquals("optional_bool: true\noptional_nested_enum: BAZ", proto);
+
+ proto = TestAllTypesLite.newBuilder()
+ .setOptionalFloat(2.72f)
+ .setOptionalDouble(3.14)
+ .build();
+ assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto);
+ }
+
+ public void testToStringStringFields() throws Exception {
+ TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+ .setOptionalString("foo\"bar\nbaz\\")
+ .build();
+ assertToStringEquals("optional_string: \"foo\\\"bar\\nbaz\\\\\"", proto);
+
+ proto = TestAllTypesLite.newBuilder()
+ .setOptionalString("\u6587")
+ .build();
+ assertToStringEquals("optional_string: \"\\346\\226\\207\"", proto);
+ }
+
+ public void testToStringNestedMessage() throws Exception {
+ TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+ .setOptionalNestedMessage(TestAllTypesLite.NestedMessage.getDefaultInstance())
+ .build();
+ assertToStringEquals("optional_nested_message {\n}", proto);
+
+ proto = TestAllTypesLite.newBuilder()
+ .setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .build();
+ assertToStringEquals("optional_nested_message {\n bb: 7\n}", proto);
+ }
+
+ public void testToStringRepeatedFields() throws Exception {
+ TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+ .addRepeatedInt32(32)
+ .addRepeatedInt32(32)
+ .addRepeatedInt64(64)
+ .build();
+ assertToStringEquals("repeated_int32: 32\nrepeated_int32: 32\nrepeated_int64: 64", proto);
+
+ proto = TestAllTypesLite.newBuilder()
+ .addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7))
+ .addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(8))
+ .build();
+ assertToStringEquals(
+ "repeated_lazy_message {\n bb: 7\n}\nrepeated_lazy_message {\n bb: 8\n}",
+ proto);
+ }
+
+ public void testToStringForeignFields() throws Exception {
+ TestAllTypesLite proto = TestAllTypesLite.newBuilder()
+ .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+ .setOptionalForeignMessage(
+ ForeignMessageLite.newBuilder()
+ .setC(3))
+ .build();
+ assertToStringEquals(
+ "optional_foreign_enum: FOREIGN_LITE_BAR\noptional_foreign_message {\n c: 3\n}",
+ proto);
+ }
+
+ public void testToStringExtensions() throws Exception {
+ TestAllExtensionsLite message = TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "spam")
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs")
+ .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+ TestAllTypesLite.NestedEnum.BAZ)
+ .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+ .build();
+ assertToStringEquals(
+ "[1]: 123\n[18] {\n bb: 7\n}\n[21]: 3\n[44]: \"spam\"\n[44]: \"eggs\"",
+ message);
+ }
+
+ public void testToStringUnknownFields() throws Exception {
+ TestAllExtensionsLite messageWithExtensions = TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "spam")
+ .addExtension(UnittestLite.repeatedStringExtensionLite, "eggs")
+ .setExtension(UnittestLite.optionalNestedEnumExtensionLite,
+ TestAllTypesLite.NestedEnum.BAZ)
+ .setExtension(UnittestLite.optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(7).build())
+ .build();
+ TestAllExtensionsLite messageWithUnknownFields = TestAllExtensionsLite.parseFrom(
+ messageWithExtensions.toByteArray());
+ assertToStringEquals(
+ "1: 123\n18: \"\\b\\a\"\n21: 3\n44: \"spam\"\n44: \"eggs\"",
+ messageWithUnknownFields);
+ }
+
+ public void testToStringLazyMessage() throws Exception {
+ TestAllTypesLite message = TestAllTypesLite.newBuilder()
+ .setOptionalLazyMessage(NestedMessage.newBuilder().setBb(1).build())
+ .build();
+ assertToStringEquals("optional_lazy_message {\n bb: 1\n}", message);
+ }
+
+ public void testToStringGroup() throws Exception {
+ TestAllTypesLite message = TestAllTypesLite.newBuilder()
+ .setOptionalGroup(OptionalGroup.newBuilder().setA(1).build())
+ .build();
+ assertToStringEquals("optional_group {\n a: 1\n}", message);
+ }
+
+ public void testToStringOneof() throws Exception {
+ TestAllTypesLite message = TestAllTypesLite.newBuilder()
+ .setOneofString("hello")
+ .build();
+ assertToStringEquals("oneof_string: \"hello\"", message);
+ }
+
+ // Asserts that the toString() representation of the message matches the expected. This verifies
+ // the first line starts with a comment; but, does not factor in said comment as part of the
+ // comparison as it contains unstable addresses.
+ private static void assertToStringEquals(String expected, MessageLite message) {
+ String toString = message.toString();
+ assertEquals('#', toString.charAt(0));
+ if (toString.indexOf("\n") >= 0) {
+ toString = toString.substring(toString.indexOf("\n") + 1);
+ } else {
+ toString = "";
+ }
+ assertEquals(expected, toString);
+ }
+
+ public void testParseLazy() throws Exception {
+ ByteString bb = TestAllTypesLite.newBuilder()
+ .setOptionalLazyMessage(NestedMessage.newBuilder()
+ .setBb(11)
+ .build())
+ .build().toByteString();
+ ByteString cc = TestAllTypesLite.newBuilder()
+ .setOptionalLazyMessage(NestedMessage.newBuilder()
+ .setCc(22)
+ .build())
+ .build().toByteString();
+
+ ByteString concat = bb.concat(cc);
+ TestAllTypesLite message = TestAllTypesLite.parseFrom(concat);
+
+ assertEquals(11, message.getOptionalLazyMessage().getBb());
+ assertEquals(22L, message.getOptionalLazyMessage().getCc());
+ }
+
+ public void testParseLazy_oneOf() throws Exception {
+ ByteString bb = TestAllTypesLite.newBuilder()
+ .setOneofLazyNestedMessage(NestedMessage.newBuilder()
+ .setBb(11)
+ .build())
+ .build().toByteString();
+ ByteString cc = TestAllTypesLite.newBuilder()
+ .setOneofLazyNestedMessage(NestedMessage.newBuilder()
+ .setCc(22)
+ .build())
+ .build().toByteString();
+
+ ByteString concat = bb.concat(cc);
+ TestAllTypesLite message = TestAllTypesLite.parseFrom(concat);
+
+ assertEquals(11, message.getOneofLazyNestedMessage().getBb());
+ assertEquals(22L, message.getOneofLazyNestedMessage().getCc());
+ }
+
+ public void testMergeFromStream_repeatedField() throws Exception {
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+ .addRepeatedString("hello");
+ builder.mergeFrom(CodedInputStream.newInstance(builder.build().toByteArray()));
+
+ assertEquals(2, builder.getRepeatedStringCount());
+ }
+
+ public void testMergeFromStream_invalidBytes() throws Exception {
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder()
+ .setDefaultBool(true);
+ try {
+ builder.mergeFrom(CodedInputStream.newInstance("Invalid bytes".getBytes(Internal.UTF_8)));
+ fail();
+ } catch (InvalidProtocolBufferException expected) {}
+ }
+
+ public void testMergeFrom_sanity() throws Exception {
+ TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+ byte[] bytes = one.toByteArray();
+ TestAllTypesLite two = TestAllTypesLite.parseFrom(bytes);
+
+ one = one.toBuilder().mergeFrom(one).build();
+ two = two.toBuilder().mergeFrom(bytes).build();
+ assertEquals(one, two);
+ assertEquals(two, one);
+ assertEquals(one.hashCode(), two.hashCode());
+ }
+
+ public void testMergeFromNoLazyFieldSharing() throws Exception {
+ TestAllTypesLite.Builder sourceBuilder = TestAllTypesLite.newBuilder().setOptionalLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(1));
+ TestAllTypesLite.Builder targetBuilder =
+ TestAllTypesLite.newBuilder().mergeFrom(sourceBuilder.build());
+ assertEquals(1, sourceBuilder.getOptionalLazyMessage().getBb());
+ // now change the sourceBuilder, and target value shouldn't be affected.
+ sourceBuilder.setOptionalLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(2));
+ assertEquals(1, targetBuilder.getOptionalLazyMessage().getBb());
+ }
+
+ public void testEquals_notEqual() throws Exception {
+ TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+ byte[] bytes = one.toByteArray();
+ TestAllTypesLite two = one.toBuilder().mergeFrom(one).mergeFrom(bytes).build();
+
+ assertFalse(one.equals(two));
+ assertFalse(two.equals(one));
+
+ assertFalse(one.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(one));
+
+ TestAllTypesLite oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultBool(true)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultCord("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultCordBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultDouble(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultFixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultFixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultFloat(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultInt32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultInt64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultNestedEnum(NestedEnum.BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultSfixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultSfixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultSint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultSint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultString("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultStringBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultStringPiece("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultStringPieceBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultUint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setDefaultUint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedBool(true)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedCord("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedCordBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedDouble(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedFixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedFixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedFloat(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedInt32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedInt64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedNestedEnum(NestedEnum.BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedSfixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedSfixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedSint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedSint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedString("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedStringBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedStringPiece("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedStringPieceBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedUint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedUint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalBool(true)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalCord("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalCordBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalDouble(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalFixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalFixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalFloat(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalImportEnum(ImportEnumLite.IMPORT_LITE_BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalInt32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalInt64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalNestedEnum(NestedEnum.BAR)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalSfixed32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalSfixed64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalSint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalSint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalString("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalStringBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalStringPiece("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalStringPieceBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalUint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalUint64(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofLazyNestedMessage(NestedMessage.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofString("")
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofStringBytes(ByteString.EMPTY)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOneofUint32(0)
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalForeignMessage(ForeignMessageLite.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalGroup(OptionalGroup.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalPublicImportMessage(PublicImportMessageLite.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .setOptionalLazyMessage(NestedMessage.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+ oneFieldSet = TestAllTypesLite.newBuilder()
+ .addRepeatedLazyMessage(NestedMessage.getDefaultInstance())
+ .build();
+ assertFalse(oneFieldSet.equals(TestAllTypesLite.getDefaultInstance()));
+ assertFalse(TestAllTypesLite.getDefaultInstance().equals(oneFieldSet));
+ }
+
+ public void testEquals() throws Exception {
+ // Check that two identical objs are equal.
+ Foo foo1a = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo1b = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo1"))
+ .build();
+ Foo foo2 = Foo.newBuilder()
+ .setValue(1)
+ .addBar(Bar.newBuilder().setName("foo2"))
+ .build();
+
+ // Check that equals is doing value rather than object equality.
+ assertEquals(foo1a, foo1b);
+ assertEquals(foo1a.hashCode(), foo1b.hashCode());
+
+ // Check that a diffeent object is not equal.
+ assertFalse(foo1a.equals(foo2));
+
+ // Check that two objects which have different types but the same field values are not
+ // considered to be equal.
+ Bar bar = Bar.newBuilder().setName("bar").build();
+ BarPrime barPrime = BarPrime.newBuilder().setName("bar").build();
+ assertFalse(bar.equals(barPrime));
+ }
+
+ public void testOneofEquals() throws Exception {
+ TestOneofEquals.Builder builder = TestOneofEquals.newBuilder();
+ TestOneofEquals message1 = builder.build();
+ // Set message2's name field to default value. The two messages should be different when we
+ // check with the oneof case.
+ builder.setName("");
+ TestOneofEquals message2 = builder.build();
+ assertFalse(message1.equals(message2));
+ }
+
+ public void testEquals_sanity() throws Exception {
+ TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
+ TestAllTypesLite two = TestAllTypesLite.parseFrom(one.toByteArray());
+ assertEquals(one, two);
+ assertEquals(one.hashCode(), two.hashCode());
+
+ assertEquals(
+ one.toBuilder().mergeFrom(two).build(),
+ two.toBuilder().mergeFrom(two.toByteArray()).build());
+ }
+
+ public void testEqualsAndHashCodeWithUnknownFields() throws InvalidProtocolBufferException {
+ Foo fooWithOnlyValue = Foo.newBuilder()
+ .setValue(1)
+ .build();
+
+ Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .build();
+
+ Foo fooWithValueAndUnknownFields = Foo.parseFrom(fooWithValueAndExtension.toByteArray());
+
+ assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndUnknownFields);
+ assertEqualsAndHashCodeAreFalse(fooWithValueAndExtension, fooWithValueAndUnknownFields);
+ }
+
+ public void testEqualsAndHashCodeWithExtensions() throws InvalidProtocolBufferException {
+ Foo fooWithOnlyValue = Foo.newBuilder()
+ .setValue(1)
+ .build();
+
+ Foo fooWithValueAndExtension = fooWithOnlyValue.toBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .build();
+
+ assertEqualsAndHashCodeAreFalse(fooWithOnlyValue, fooWithValueAndExtension);
+ }
+
+ // Test to ensure we avoid a class cast exception with oneofs.
+ public void testEquals_oneOfMessages() {
+ TestAllTypesLite mine = TestAllTypesLite.newBuilder()
+ .setOneofString("Hello")
+ .build();
+
+ TestAllTypesLite other = TestAllTypesLite.newBuilder()
+ .setOneofNestedMessage(NestedMessage.getDefaultInstance())
+ .build();
+
+ assertFalse(mine.equals(other));
+ assertFalse(other.equals(mine));
+ }
+
+ public void testHugeFieldNumbers() throws InvalidProtocolBufferException {
+ TestHugeFieldNumbersLite message =
+ TestHugeFieldNumbersLite.newBuilder()
+ .setOptionalInt32(1)
+ .addRepeatedInt32(2)
+ .setOptionalEnum(ForeignEnumLite.FOREIGN_LITE_FOO)
+ .setOptionalString("xyz")
+ .setOptionalMessage(ForeignMessageLite.newBuilder().setC(3).build())
+ .build();
+
+ TestHugeFieldNumbersLite parsedMessage =
+ TestHugeFieldNumbersLite.parseFrom(message.toByteArray());
+ assertEquals(1, parsedMessage.getOptionalInt32());
+ assertEquals(2, parsedMessage.getRepeatedInt32(0));
+ assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO, parsedMessage.getOptionalEnum());
+ assertEquals("xyz", parsedMessage.getOptionalString());
+ assertEquals(3, parsedMessage.getOptionalMessage().getC());
+ }
+
+ private void assertEqualsAndHashCodeAreFalse(Object o1, Object o2) {
+ assertFalse(o1.equals(o2));
+ assertFalse(o1.hashCode() == o2.hashCode());
+ }
+
+ public void testRecursiveHashcode() {
+ // This tests that we don't infinite loop.
+ TestRecursiveOneof.getDefaultInstance().hashCode();
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
new file mode 100644
index 0000000000..eac47448e0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java
@@ -0,0 +1,544 @@
+// 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.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+import junit.framework.TestCase;
+
+/**
+ * Test {@code LiteralByteString} by setting up a reference string in {@link #setUp()}.
+ * This class is designed to be extended for testing extensions of {@code LiteralByteString}
+ * such as {@code BoundedByteString}, see {@link BoundedByteStringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class LiteralByteStringTest extends TestCase {
+ protected static final String UTF_8 = "UTF-8";
+
+ protected String classUnderTest;
+ protected byte[] referenceBytes;
+ protected ByteString stringUnderTest;
+ protected int expectedHashCode;
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "LiteralByteString";
+ referenceBytes = ByteStringTest.getTestBytes(1234, 11337766L);
+ stringUnderTest = ByteString.copyFrom(referenceBytes);
+ expectedHashCode = 331161852;
+ }
+
+ public void testExpectedType() {
+ String actualClassName = getActualClassName(stringUnderTest);
+ assertEquals(classUnderTest + " should match type exactly", classUnderTest, actualClassName);
+ }
+
+ protected String getActualClassName(Object object) {
+ return object.getClass().getSimpleName();
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (referenceBytes[i] == stringUnderTest.byteAt(i));
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = stringUnderTest.iterator();
+ for (int i = 0; stillEqual && i < referenceBytes.length; ++i) {
+ stillEqual = (iter.hasNext() && referenceBytes[i] == iter.nextByte());
+ }
+ assertTrue(classUnderTest + " must capture the right bytes", stillEqual);
+ assertFalse(classUnderTest + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : stringUnderTest) {
+ stillEqual = (referenceBytes[j] == quantum);
+ ++j;
+ }
+ assertTrue(classUnderTest + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(classUnderTest + " iterable character count", referenceBytes.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(classUnderTest + " must have the expected size", referenceBytes.length,
+ stringUnderTest.size());
+ }
+
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have depth 0", 0, stringUnderTest.getTreeDepth());
+ }
+
+ public void testIsBalanced() {
+ assertTrue(classUnderTest + " is technically balanced", stringUnderTest.isBalanced());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ stringUnderTest.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = referenceBytes[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(classUnderTest + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ stringUnderTest.copyTo(destination, stringUnderTest.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ stringUnderTest.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ stringUnderTest.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ stringUnderTest.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ stringUnderTest.copyTo(destination, 2 * stringUnderTest.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ stringUnderTest.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + classUnderTest);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ ByteBuffer myBuffer = ByteBuffer.allocate(referenceBytes.length);
+ stringUnderTest.copyTo(myBuffer);
+ assertTrue(classUnderTest + ".copyTo(ByteBuffer) must give back the same bytes",
+ Arrays.equals(referenceBytes, myBuffer.array()));
+ }
+
+ public void testMarkSupported() {
+ InputStream stream = stringUnderTest.newInput();
+ assertTrue(classUnderTest + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = stringUnderTest.size() / 3;
+
+ InputStream stream = stringUnderTest.newInput();
+ stream.mark(stringUnderTest.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ int available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the 'middle', half the bytes are available",
+ (stringUnderTest.size() - fraction) == available);
+ stream.reset();
+
+ skipFully(stream, stringUnderTest.size()); // Skip to the end.
+ available = stream.available();
+ assertTrue(
+ classUnderTest + ": after skipping to the end, no more bytes are available",
+ 0 == available);
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = stringUnderTest.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ assertTrue(byteBuffer.remaining() == referenceBytes.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(classUnderTest + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = stringUnderTest.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[referenceBytes.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= referenceBytes.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == referenceBytes.length);
+ assertTrue(classUnderTest + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = stringUnderTest.toByteArray();
+ assertTrue(classUnderTest + ".toByteArray() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ stringUnderTest.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(classUnderTest + ".writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ }
+
+ public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ Arrays.fill(b, off, off + len, (byte) 0);
+ }
+
+ @Override
+ public void write(int b) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ stringUnderTest.writeTo(os);
+ assertTrue(classUnderTest + ".writeTo() must not grant access to underlying array",
+ Arrays.equals(referenceBytes, stringUnderTest.toByteArray()));
+ }
+
+ public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ Arrays.fill(b, off, off + len, (byte) 0);
+ }
+
+ @Override
+ public void write(int b) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ stringUnderTest.writeToInternal(os, 0, stringUnderTest.size());
+ byte[] allZeros = new byte[stringUnderTest.size()];
+ assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array",
+ Arrays.equals(allZeros, stringUnderTest.toByteArray()));
+ }
+
+ public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException {
+ ByteOutput out = new ByteOutput() {
+ @Override
+ public void write(byte value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ Arrays.fill(value, offset, offset + length, (byte) 0);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ stringUnderTest.writeTo(out);
+ byte[] allZeros = new byte[stringUnderTest.size()];
+ assertTrue(classUnderTest + ".writeToInternal() must grant access to underlying array",
+ Arrays.equals(allZeros, stringUnderTest.toByteArray()));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ stringUnderTest.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), stringUnderTest.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(referenceBytes, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ stringUnderTest.concat(stringUnderTest), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ ByteString.EMPTY, output.toByteString());
+ }
+
+ public void testToString() throws UnsupportedEncodingException {
+ String testString = "I love unicode \u1234\u5678 characters";
+ 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";
+ ByteString unicode = ByteString.wrap(testString.getBytes(Internal.UTF_8));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode must match", testString, roundTripString);
+ }
+
+ public void testToString_returnsCanonicalEmptyString() {
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(Internal.UTF_8),
+ ByteString.wrap(new byte[]{}).toString(Internal.UTF_8));
+ }
+
+ public void testToString_raisesException() {
+ try {
+ ByteString.EMPTY.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ ByteString.wrap(referenceBytes).toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ public void testEquals() {
+ assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null));
+ assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest);
+ assertFalse(classUnderTest + " must not equal the empty string",
+ stringUnderTest.equals(ByteString.EMPTY));
+ assertEquals(classUnderTest + " empty strings must be equal",
+ ByteString.wrap(new byte[]{}), stringUnderTest.substring(55, 55));
+ assertEquals(classUnderTest + " must equal another string with the same value",
+ 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(ByteString.wrap(mungedBytes)));
+ }
+
+ public void testHashCode() {
+ int hash = stringUnderTest.hashCode();
+ assertEquals(classUnderTest + " must have expected hashCode", expectedHashCode, hash);
+ }
+
+ public void testPeekCachedHashCode() {
+ assertEquals(classUnderTest + ".peekCachedHashCode() should return zero at first", 0,
+ stringUnderTest.peekCachedHashCode());
+ stringUnderTest.hashCode();
+ assertEquals(classUnderTest + ".peekCachedHashCode should return zero at first",
+ expectedHashCode, stringUnderTest.peekCachedHashCode());
+ }
+
+ public void testPartialHash() {
+ // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+ // This test would fail if the expected hash were 1. It's not.
+ int hash = stringUnderTest.partialHash(stringUnderTest.size(), 0, stringUnderTest.size());
+ assertEquals(classUnderTest + ".partialHash() must yield expected hashCode",
+ expectedHashCode, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ stringUnderTest.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : referenceBytes) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(classUnderTest + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(classUnderTest + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = stringUnderTest.newInput();
+ int stringSize = stringUnderTest.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ stringUnderTest.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = stringUnderTest.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(referenceBytes.length);
+ assertTrue(classUnderTest + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(referenceBytes, roundTripBytes));
+ assertTrue(classUnderTest + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(classUnderTest + " concatenated with empty must give " + classUnderTest,
+ stringUnderTest.concat(ByteString.EMPTY), stringUnderTest);
+ assertSame("empty concatenated with " + classUnderTest + " must give " + classUnderTest,
+ ByteString.EMPTY.concat(stringUnderTest), stringUnderTest);
+ }
+
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
new file mode 100644
index 0000000000..6bbdfcaa32
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/LongArrayListTest.java
@@ -0,0 +1,461 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link LongArrayList}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class LongArrayListTest extends TestCase {
+
+ private static final LongArrayList UNARY_LIST =
+ newImmutableLongArrayList(1);
+ private static final LongArrayList TERTIARY_LIST =
+ newImmutableLongArrayList(1, 2, 3);
+
+ private LongArrayList list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new LongArrayList();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(LongArrayList.emptyList(), LongArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(LongArrayList.emptyList());
+ }
+
+ public void testMakeImmutable() {
+ list.addLong(3);
+ list.addLong(4);
+ list.addLong(5);
+ list.addLong(7);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1L, 2L, 3L, 4L));
+ Iterator<Long> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1L, (long) list.get(0));
+ assertEquals(1L, (long) iterator.next());
+ list.set(0, 1L);
+ assertEquals(2L, (long) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0L);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testGet() {
+ assertEquals(1L, (long) TERTIARY_LIST.get(0));
+ assertEquals(2L, (long) TERTIARY_LIST.get(1));
+ assertEquals(3L, (long) TERTIARY_LIST.get(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testGetLong() {
+ assertEquals(1L, TERTIARY_LIST.getLong(0));
+ assertEquals(2L, TERTIARY_LIST.getLong(1));
+ assertEquals(3L, TERTIARY_LIST.getLong(2));
+
+ try {
+ TERTIARY_LIST.get(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ TERTIARY_LIST.get(3);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSize() {
+ assertEquals(0, LongArrayList.emptyList().size());
+ assertEquals(1, UNARY_LIST.size());
+ assertEquals(3, TERTIARY_LIST.size());
+
+ list.addLong(3);
+ list.addLong(4);
+ list.addLong(6);
+ list.addLong(8);
+ assertEquals(4, list.size());
+
+ list.remove(0);
+ assertEquals(3, list.size());
+
+ list.add(17L);
+ assertEquals(4, list.size());
+ }
+
+ public void testSet() {
+ list.addLong(2);
+ list.addLong(4);
+
+ assertEquals(2L, (long) list.set(0, 3L));
+ assertEquals(3L, list.getLong(0));
+
+ assertEquals(4L, (long) list.set(1, 0L));
+ assertEquals(0L, list.getLong(1));
+
+ try {
+ list.set(-1, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.set(2, 0L);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSetLong() {
+ list.addLong(1);
+ list.addLong(3);
+
+ assertEquals(1L, list.setLong(0, 0));
+ assertEquals(0L, list.getLong(0));
+
+ assertEquals(3L, list.setLong(1, 0));
+ assertEquals(0L, list.getLong(1));
+
+ try {
+ list.setLong(-1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAdd() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.add(2L));
+ assertEquals(asList(2L), list);
+
+ assertTrue(list.add(3L));
+ list.add(0, 4L);
+ assertEquals(asList(4L, 2L, 3L), list);
+
+ list.add(0, 1L);
+ list.add(0, 0L);
+ // Force a resize by getting up to 11 elements.
+ for (int i = 0; i < 6; i++) {
+ list.add(Long.valueOf(5 + i));
+ }
+ assertEquals(
+ asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L),
+ list);
+
+ try {
+ list.add(-1, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.add(4, 5L);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testAddLong() {
+ assertEquals(0, list.size());
+
+ list.addLong(2);
+ assertEquals(asList(2L), list);
+
+ list.addLong(3);
+ assertEquals(asList(2L, 3L), list);
+ }
+
+ public void testAddAll() {
+ assertEquals(0, list.size());
+
+ assertTrue(list.addAll(Collections.singleton(1L)));
+ assertEquals(1, list.size());
+ assertEquals(1L, (long) list.get(0));
+ assertEquals(1L, list.getLong(0));
+
+ assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L)));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list);
+
+ assertTrue(list.addAll(TERTIARY_LIST));
+ assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list);
+
+ assertFalse(list.addAll(Collections.<Long>emptyList()));
+ assertFalse(list.addAll(LongArrayList.emptyList()));
+ }
+
+ public void testRemove() {
+ list.addAll(TERTIARY_LIST);
+ assertEquals(1L, (long) list.remove(0));
+ assertEquals(asList(2L, 3L), list);
+
+ assertTrue(list.remove(Long.valueOf(3)));
+ assertEquals(asList(2L), list);
+
+ assertFalse(list.remove(Long.valueOf(3)));
+ assertEquals(asList(2L), list);
+
+ assertEquals(2L, (long) list.remove(0));
+ assertEquals(asList(), list);
+
+ try {
+ list.remove(-1);
+ fail();
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ list.remove(0);
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ private void assertImmutable(LongArrayList list) {
+ if (list.contains(1L)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new LongArrayList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addLong(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.<Long>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1L));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0L);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.setLong(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static LongArrayList newImmutableLongArrayList(long... elements) {
+ LongArrayList list = new LongArrayList();
+ for (long element : elements) {
+ list.addLong(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
new file mode 100644
index 0000000000..0a14f58417
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -0,0 +1,796 @@
+// 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 map_lite_test.MapForProto2TestProto.BizarroTestMap;
+import map_lite_test.MapForProto2TestProto.TestMap;
+import map_lite_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_lite_test.MapForProto2TestProto.TestMapOrBuilder;
+import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for map fields.
+ */
+public final class MapForProto2LiteTest extends TestCase {
+
+ private void setMapValues(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 11)
+ .putInt32ToInt32Field(2, 22)
+ .putInt32ToInt32Field(3, 33)
+
+ .putInt32ToStringField(1, "11")
+ .putInt32ToStringField(2, "22")
+ .putInt32ToStringField(3, "33")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("11"))
+ .putInt32ToBytesField(2, TestUtil.toBytes("22"))
+ .putInt32ToBytesField(3, TestUtil.toBytes("33"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
+ .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
+ .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
+ .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
+ .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
+
+ .putStringToInt32Field("1", 11)
+ .putStringToInt32Field("2", 22)
+ .putStringToInt32Field("3", 33);
+ }
+
+ public void testSetMapValues() {
+ TestMap.Builder mapBuilder = TestMap.newBuilder();
+ setMapValues(mapBuilder);
+ TestMap map = mapBuilder.build();
+ assertMapValuesSet(map);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValues(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 111)
+ .removeInt32ToInt32Field(2)
+ .putInt32ToInt32Field(4, 44)
+
+ .putInt32ToStringField(1, "111")
+ .removeInt32ToStringField(2)
+ .putInt32ToStringField(4, "44")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("111"))
+ .removeInt32ToBytesField(2)
+ .putInt32ToBytesField(4, TestUtil.toBytes("44"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
+ .removeInt32ToEnumField(2)
+ .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
+ .removeInt32ToMessageField(2)
+ .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
+
+ .putStringToInt32Field("1", 111)
+ .removeStringToInt32Field("2")
+ .putStringToInt32Field("4", 44);
+ }
+
+ public void testUpdateMapValues() {
+ TestMap.Builder mapBuilder = TestMap.newBuilder();
+ setMapValues(mapBuilder);
+ TestMap map = mapBuilder.build();
+ assertMapValuesSet(map);
+
+ mapBuilder = map.toBuilder();
+ updateMapValues(mapBuilder);
+ map = mapBuilder.build();
+ assertMapValuesUpdated(map);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
+ // Since builders are implemented as a thin wrapper around a message
+ // instance, we attempt to verify that we can't cause the builder to modify
+ // a produced message.
+
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ builder.putInt32ToInt32Field(1, 2);
+ assertTrue(message.getInt32ToInt32Field().isEmpty());
+ message = builder.build();
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.putInt32ToInt32Field(2, 3);
+ assertEquals(newMap(1, 2), message.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+ }
+
+ public void testGetMapIsImmutable() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+
+ setMapValues(builder);
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+ }
+
+ private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
+ assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
+ assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
+ assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
+ assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+ assertImmutable(
+ testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
+ assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+ }
+
+ private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
+ try {
+ map.put(key, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ if (!map.isEmpty()) {
+ try {
+ map.entrySet().remove(map.entrySet().iterator().next());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putInt32ToInt32Field(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.putInt32ToInt32Field(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+
+ builder.putInt32ToEnumField(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.putInt32ToEnumField(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+
+ builder.putInt32ToStringField(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.putInt32ToStringField(2, "2");
+ assertEquals(newMap(1, "1", 2, "2"), builder.getInt32ToStringField());
+
+ builder.putInt32ToMessageField(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValues(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ assertMapValuesCleared(builder);
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValues(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+ assertMapValuesSet(source);
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testPutChecksNullKeysAndValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToMessageField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putStringToInt32Field(null, 1);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValues(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ bizarroMap.writeTo(output);
+ output.flush();
+ return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
+ }
+
+ public void testParseError() throws Exception {
+ ByteString bytes = TestUtil.toBytes("SOME BYTES");
+ String stringKey = "a string key";
+
+ TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToInt32Field(5, bytes)
+ .build());
+ assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToStringField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToBytesField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToEnumField(stringKey, bytes)
+ .build());
+ assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+
+ try {
+ tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToMessageField(stringKey, bytes)
+ .build());
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
+ map = (TestMap) expected.getUnfinishedMessage();
+ assertTrue(map.getInt32ToMessageField().isEmpty());
+ }
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putStringToInt32Field(stringKey, bytes)
+ .build());
+ assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder()
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4)
+ .putInt32ToInt32Field(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder()
+ .putInt32ToInt32Field(5, 6)
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.putInt32ToInt32Field(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder()
+ .putInt32ToInt32Field(1, 1)
+ .putInt32ToInt32Field(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testGetMap() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+ assertEquals(
+ message.getStringToInt32Field(),
+ message.getStringToInt32FieldMap());
+ assertEquals(
+ message.getInt32ToBytesField(),
+ message.getInt32ToBytesFieldMap());
+ assertEquals(
+ message.getInt32ToEnumField(),
+ message.getInt32ToEnumFieldMap());
+ assertEquals(
+ message.getInt32ToMessageField(),
+ message.getInt32ToMessageFieldMap());
+ }
+
+ public void testContains() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ assertMapContainsSetValues(builder);
+ assertMapContainsSetValues(builder.build());
+ }
+
+ private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
+ assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
+
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
+ assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
+ }
+
+ public void testCount() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+
+ setMapValues(builder);
+ assertMapCounts(3, builder);
+
+ TestMap message = builder.build();
+ assertMapCounts(3, message);
+
+ builder = message.toBuilder().putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ assertEquals(4, builder.build().getInt32ToInt32FieldCount());
+
+ // already present - should be unchanged
+ builder.putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ }
+
+ private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testGetOrDefault() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValues(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
+ assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
+ assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
+ assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testGetOrThrow() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValues(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPut() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.putInt32ToInt32Field(1, 11);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+
+ builder.putInt32ToStringField(1, "a");
+ assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putStringToInt32Field("a", 1);
+ assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
+ try {
+ builder.putStringToInt32Field(null, -1);
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testRemove() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToInt32Field(1);
+ assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
+ }
+
+ assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToStringField(1);
+ assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToBytesField(1);
+ assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToEnumField(1);
+ assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
+ }
+
+ assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
+ for (int times = 0; times < 2; times++) {
+ builder.removeStringToInt32Field("1");
+ assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
+ }
+
+ try {
+ builder.removeStringToInt32Field(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
new file mode 100644
index 0000000000..cfe4c4536e
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -0,0 +1,1178 @@
+// 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 com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapForProto2TestProto.BizarroTestMap;
+import map_test.MapForProto2TestProto.ReservedAsMapField;
+import map_test.MapForProto2TestProto.ReservedAsMapFieldWithEnumValue;
+import map_test.MapForProto2TestProto.TestMap;
+import map_test.MapForProto2TestProto.TestMap.MessageValue;
+import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields;
+import map_test.MapForProto2TestProto.TestMapOrBuilder;
+import map_test.MapForProto2TestProto.TestRecursiveMap;
+import map_test.MapForProto2TestProto.TestUnknownEnumValue;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for map fields in proto2 protos.
+ */
+public class MapForProto2Test extends TestCase {
+
+ private void setMapValuesUsingMutableMap(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+ //
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+ //
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+ //
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+ //
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+ //
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void setMapValuesUsingAccessors(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 11)
+ .putInt32ToInt32Field(2, 22)
+ .putInt32ToInt32Field(3, 33)
+
+ .putInt32ToStringField(1, "11")
+ .putInt32ToStringField(2, "22")
+ .putInt32ToStringField(3, "33")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("11"))
+ .putInt32ToBytesField(2, TestUtil.toBytes("22"))
+ .putInt32ToBytesField(3, TestUtil.toBytes("33"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
+ .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
+ .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
+ .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
+ .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
+
+ .putStringToInt32Field("1", 11)
+ .putStringToInt32Field("2", 22)
+ .putStringToInt32Field("3", 33);
+ }
+
+ public void testSetMapValues() {
+ TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
+ setMapValuesUsingMutableMap(usingMutableMapBuilder);
+ TestMap usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesSet(usingMutableMap);
+
+ TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(usingAccessorsBuilder);
+ TestMap usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesSet(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMapOrBuilder message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+ //
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+ //
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+ //
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+ //
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+ //
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void updateMapValuesUsingAccessors(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 111)
+ .removeInt32ToInt32Field(2)
+ .putInt32ToInt32Field(4, 44)
+
+ .putInt32ToStringField(1, "111")
+ .removeInt32ToStringField(2)
+ .putInt32ToStringField(4, "44")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("111"))
+ .removeInt32ToBytesField(2)
+ .putInt32ToBytesField(4, TestUtil.toBytes("44"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
+ .removeInt32ToEnumField(2)
+ .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
+ .removeInt32ToMessageField(2)
+ .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
+
+ .putStringToInt32Field("1", 111)
+ .removeStringToInt32Field("2")
+ .putStringToInt32Field("4", 44);
+ }
+
+ public void testUpdateMapValues() {
+ TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
+ setMapValuesUsingMutableMap(usingMutableMapBuilder);
+ TestMap usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesSet(usingMutableMap);
+
+ TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(usingAccessorsBuilder);
+ TestMap usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesSet(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ //
+ usingMutableMapBuilder = usingMutableMap.toBuilder();
+ updateMapValuesUsingMutableMap(usingMutableMapBuilder);
+ usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesUpdated(usingMutableMap);
+
+ usingAccessorsBuilder = usingAccessors.toBuilder();
+ updateMapValuesUsingAccessors(usingAccessorsBuilder);
+ usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesUpdated(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testGetMapIsImmutable() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+
+ setMapValuesUsingAccessors(builder);
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+ }
+
+ private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
+ assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
+ assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
+ assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
+ assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+ assertImmutable(
+ testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
+ assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+ }
+
+ private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
+ try {
+ map.put(key, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+ //
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+ //
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.getMutableInt32ToStringField().put(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+ //
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+ //
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ assertMapValuesCleared(builder);
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+ assertMapValuesSet(source);
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+
+ assertEquals(3, destination.getInt32ToEnumFieldCount());
+ }
+
+ public void testPutChecksNullKeysAndValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToMessageField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putStringToInt32Field(null, 1);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ bizarroMap.writeTo(output);
+ output.flush();
+ return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
+ }
+
+ public void testParseError() throws Exception {
+ ByteString bytes = TestUtil.toBytes("SOME BYTES");
+ String stringKey = "a string key";
+
+ TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToInt32Field(5, bytes)
+ .build());
+ assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToStringField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToBytesField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToEnumField(stringKey, bytes)
+ .build());
+ assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+
+ try {
+ tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToMessageField(stringKey, bytes)
+ .build());
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
+ map = (TestMap) expected.getUnfinishedMessage();
+ assertTrue(map.getInt32ToMessageField().isEmpty());
+ }
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putStringToInt32Field(stringKey, bytes)
+ .build());
+ assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder();
+ b1.putInt32ToInt32Field(1, 2);
+ b1.putInt32ToInt32Field(3, 4);
+ b1.putInt32ToInt32Field(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder();
+ b2.putInt32ToInt32Field(5, 6);
+ b2.putInt32ToInt32Field(1, 2);
+ b2.putInt32ToInt32Field(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.putInt32ToInt32Field(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType> Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4)
+ .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
+ .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestUnknownEnumValue.Builder builder = TestUnknownEnumValue.newBuilder()
+ .putInt32ToInt32Field(1, 1)
+ .putInt32ToInt32Field(2, 54321);
+ ByteString data = builder.build().toByteString();
+
+ TestMap message = TestMap.parseFrom(data);
+ // Entries with unknown enum values will be stored into UnknownFieldSet so
+ // there is only one entry in the map.
+ assertEquals(1, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ // UnknownFieldSet should not be empty.
+ assertFalse(message.getUnknownFields().asMap().isEmpty());
+ // Serializing and parsing should preserve the unknown entry.
+ data = message.toByteString();
+ TestUnknownEnumValue messageWithUnknownEnums =
+ TestUnknownEnumValue.parseFrom(data);
+ assertEquals(2, messageWithUnknownEnums.getInt32ToInt32Field().size());
+ assertEquals(1, messageWithUnknownEnums.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue());
+ }
+
+ public void testRequiredMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.putRequiredMessageMap(0, MessageWithRequiredFields.newBuilder().buildPartial());
+ TestMap message = builder.buildPartial();
+ assertFalse(message.isInitialized());
+
+ builder.putRequiredMessageMap(0, MessageWithRequiredFields.newBuilder().setValue(1).build());
+ message = builder.build();
+ assertTrue(message.isInitialized());
+ }
+
+ public void testRecursiveMap() throws Exception {
+ TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder();
+ builder.putRecursiveMapField(1, TestRecursiveMap.newBuilder().setValue(2).build());
+ builder.putRecursiveMapField(3, TestRecursiveMap.newBuilder().setValue(4).build());
+ ByteString data = builder.build().toByteString();
+
+ TestRecursiveMap message = TestRecursiveMap.parseFrom(data);
+ assertEquals(2, message.getRecursiveMapField().get(1).getValue());
+ assertEquals(4, message.getRecursiveMapField().get(3).getValue());
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ public void testContains() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ assertMapContainsSetValues(builder);
+ assertMapContainsSetValues(builder.build());
+ }
+
+ private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
+ assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
+
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
+ assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
+ }
+
+ public void testCount() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+
+ setMapValuesUsingAccessors(builder);
+ assertMapCounts(3, builder);
+
+ TestMap message = builder.build();
+ assertMapCounts(3, message);
+
+ builder = message.toBuilder().putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ assertEquals(4, builder.build().getInt32ToInt32FieldCount());
+
+ // already present - should be unchanged
+ builder.putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ }
+
+ private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testGetOrDefault() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValuesUsingAccessors(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
+ assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
+ assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
+ assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testGetOrThrow() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValuesUsingAccessors(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPut() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.putInt32ToInt32Field(1, 11);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+
+ builder.putInt32ToStringField(1, "a");
+ assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putStringToInt32Field("a", 1);
+ assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
+ try {
+ builder.putStringToInt32Field(null, -1);
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testRemove() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToInt32Field(1);
+ assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
+ }
+
+ assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToStringField(1);
+ assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToBytesField(1);
+ assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToEnumField(1);
+ assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
+ }
+
+ assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
+ for (int times = 0; times < 2; times++) {
+ builder.removeStringToInt32Field("1");
+ assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
+ }
+
+ try {
+ builder.removeStringToInt32Field(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ // Regression test for b/20494788
+ public void testMapInitializationOrder() throws Exception {
+ assertEquals("RedactAllTypes", map_test.RedactAllTypes
+ .getDefaultInstance().getDescriptorForType().getName());
+
+ map_test.Message1.Builder builder =
+ map_test.Message1.newBuilder();
+ builder.putMapField("key", true);
+ map_test.Message1 message = builder.build();
+ Message mapEntry = (Message) message.getRepeatedField(
+ message.getDescriptorForType().findFieldByName("map_field"), 0);
+ assertEquals(2, mapEntry.getAllFields().size());
+ }
+
+ public void testReservedWordsFieldNames() {
+ ReservedAsMapField.newBuilder().build();
+ ReservedAsMapFieldWithEnumValue.newBuilder().build();
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testGetMap() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ assertMapValuesSet(builder);
+ TestMap message = builder.build();
+ assertEquals(
+ message.getStringToInt32Field(),
+ message.getStringToInt32FieldMap());
+ assertEquals(
+ message.getInt32ToBytesField(),
+ message.getInt32ToBytesFieldMap());
+ assertEquals(
+ message.getInt32ToEnumField(),
+ message.getInt32ToEnumFieldMap());
+ assertEquals(
+ message.getInt32ToMessageField(),
+ message.getInt32ToMessageFieldMap());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapTest.java
new file mode 100644
index 0000000000..81e951ccf7
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -0,0 +1,1495 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import map_test.MapTestProto.BizarroTestMap;
+import map_test.MapTestProto.ReservedAsMapField;
+import map_test.MapTestProto.ReservedAsMapFieldWithEnumValue;
+import map_test.MapTestProto.TestMap;
+import map_test.MapTestProto.TestMap.MessageValue;
+import map_test.MapTestProto.TestMapOrBuilder;
+import map_test.MapTestProto.TestOnChangeEventPropagation;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for map fields.
+ */
+public class MapTest extends TestCase {
+
+ private void setMapValuesUsingMutableMap(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 11);
+ builder.getMutableInt32ToInt32Field().put(2, 22);
+ builder.getMutableInt32ToInt32Field().put(3, 33);
+ //
+ builder.getMutableInt32ToStringField().put(1, "11");
+ builder.getMutableInt32ToStringField().put(2, "22");
+ builder.getMutableInt32ToStringField().put(3, "33");
+ //
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
+ builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
+ builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
+ //
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
+ //
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(11).build());
+ builder.getMutableInt32ToMessageField().put(
+ 2, MessageValue.newBuilder().setValue(22).build());
+ builder.getMutableInt32ToMessageField().put(
+ 3, MessageValue.newBuilder().setValue(33).build());
+ //
+ builder.getMutableStringToInt32Field().put("1", 11);
+ builder.getMutableStringToInt32Field().put("2", 22);
+ builder.getMutableStringToInt32Field().put("3", 33);
+ }
+
+ private void setMapValuesUsingAccessors(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 11)
+ .putInt32ToInt32Field(2, 22)
+ .putInt32ToInt32Field(3, 33)
+
+ .putInt32ToStringField(1, "11")
+ .putInt32ToStringField(2, "22")
+ .putInt32ToStringField(3, "33")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("11"))
+ .putInt32ToBytesField(2, TestUtil.toBytes("22"))
+ .putInt32ToBytesField(3, TestUtil.toBytes("33"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.FOO)
+ .putInt32ToEnumField(2, TestMap.EnumValue.BAR)
+ .putInt32ToEnumField(3, TestMap.EnumValue.BAZ)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(11).build())
+ .putInt32ToMessageField(2, MessageValue.newBuilder().setValue(22).build())
+ .putInt32ToMessageField(3, MessageValue.newBuilder().setValue(33).build())
+
+ .putStringToInt32Field("1", 11)
+ .putStringToInt32Field("2", 22)
+ .putStringToInt32Field("3", 33);
+ }
+
+ public void testSetMapValues() {
+ TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
+ setMapValuesUsingMutableMap(usingMutableMapBuilder);
+ TestMap usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesSet(usingMutableMap);
+
+ TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(usingAccessorsBuilder);
+ TestMap usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesSet(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ }
+
+ private void copyMapValues(TestMap source, TestMap.Builder destination) {
+ destination
+ .putAllInt32ToInt32Field(source.getInt32ToInt32Field())
+ .putAllInt32ToStringField(source.getInt32ToStringField())
+ .putAllInt32ToBytesField(source.getInt32ToBytesField())
+ .putAllInt32ToEnumField(source.getInt32ToEnumField())
+ .putAllInt32ToMessageField(source.getInt32ToMessageField())
+ .putAllStringToInt32Field(source.getStringToInt32Field());
+ }
+
+ private void assertMapValuesSet(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(11, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(22, message.getInt32ToInt32Field().get(2).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("11", message.getInt32ToStringField().get(1));
+ assertEquals("22", message.getInt32ToStringField().get(2));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("11"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("22"), message.getInt32ToBytesField().get(2));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.FOO, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(2));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(11, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(22, message.getInt32ToMessageField().get(2).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(11, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(22, message.getStringToInt32Field().get("2").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ }
+
+ private void updateMapValuesUsingMutableMap(TestMap.Builder builder) {
+ builder.getMutableInt32ToInt32Field().put(1, 111);
+ builder.getMutableInt32ToInt32Field().remove(2);
+ builder.getMutableInt32ToInt32Field().put(4, 44);
+ //
+ builder.getMutableInt32ToStringField().put(1, "111");
+ builder.getMutableInt32ToStringField().remove(2);
+ builder.getMutableInt32ToStringField().put(4, "44");
+ //
+ builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
+ builder.getMutableInt32ToBytesField().remove(2);
+ builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
+ //
+ builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
+ builder.getMutableInt32ToEnumField().remove(2);
+ builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
+ //
+ builder.getMutableInt32ToMessageField().put(
+ 1, MessageValue.newBuilder().setValue(111).build());
+ builder.getMutableInt32ToMessageField().remove(2);
+ builder.getMutableInt32ToMessageField().put(
+ 4, MessageValue.newBuilder().setValue(44).build());
+ //
+ builder.getMutableStringToInt32Field().put("1", 111);
+ builder.getMutableStringToInt32Field().remove("2");
+ builder.getMutableStringToInt32Field().put("4", 44);
+ }
+
+ private void updateMapValuesUsingAccessors(TestMap.Builder builder) {
+ builder
+ .putInt32ToInt32Field(1, 111)
+ .removeInt32ToInt32Field(2)
+ .putInt32ToInt32Field(4, 44)
+
+ .putInt32ToStringField(1, "111")
+ .removeInt32ToStringField(2)
+ .putInt32ToStringField(4, "44")
+
+ .putInt32ToBytesField(1, TestUtil.toBytes("111"))
+ .removeInt32ToBytesField(2)
+ .putInt32ToBytesField(4, TestUtil.toBytes("44"))
+
+ .putInt32ToEnumField(1, TestMap.EnumValue.BAR)
+ .removeInt32ToEnumField(2)
+ .putInt32ToEnumField(4, TestMap.EnumValue.QUX)
+
+ .putInt32ToMessageField(1, MessageValue.newBuilder().setValue(111).build())
+ .removeInt32ToMessageField(2)
+ .putInt32ToMessageField(4, MessageValue.newBuilder().setValue(44).build())
+
+ .putStringToInt32Field("1", 111)
+ .removeStringToInt32Field("2")
+ .putStringToInt32Field("4", 44);
+ }
+
+ public void testUpdateMapValues() {
+ TestMap.Builder usingMutableMapBuilder = TestMap.newBuilder();
+ setMapValuesUsingMutableMap(usingMutableMapBuilder);
+ TestMap usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesSet(usingMutableMap);
+
+ TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(usingAccessorsBuilder);
+ TestMap usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesSet(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ //
+ usingMutableMapBuilder = usingMutableMap.toBuilder();
+ updateMapValuesUsingMutableMap(usingMutableMapBuilder);
+ usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesUpdated(usingMutableMap);
+
+ usingAccessorsBuilder = usingAccessors.toBuilder();
+ updateMapValuesUsingAccessors(usingAccessorsBuilder);
+ usingAccessors = usingAccessorsBuilder.build();
+ assertMapValuesUpdated(usingAccessors);
+
+ assertEquals(usingAccessors, usingMutableMap);
+ }
+
+ private void assertMapValuesUpdated(TestMap message) {
+ assertEquals(3, message.getInt32ToInt32Field().size());
+ assertEquals(111, message.getInt32ToInt32Field().get(1).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(3).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(4).intValue());
+
+ assertEquals(3, message.getInt32ToStringField().size());
+ assertEquals("111", message.getInt32ToStringField().get(1));
+ assertEquals("33", message.getInt32ToStringField().get(3));
+ assertEquals("44", message.getInt32ToStringField().get(4));
+
+ assertEquals(3, message.getInt32ToBytesField().size());
+ assertEquals(TestUtil.toBytes("111"), message.getInt32ToBytesField().get(1));
+ assertEquals(TestUtil.toBytes("33"), message.getInt32ToBytesField().get(3));
+ assertEquals(TestUtil.toBytes("44"), message.getInt32ToBytesField().get(4));
+
+ assertEquals(3, message.getInt32ToEnumField().size());
+ assertEquals(TestMap.EnumValue.BAR, message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.BAZ, message.getInt32ToEnumField().get(3));
+ assertEquals(TestMap.EnumValue.QUX, message.getInt32ToEnumField().get(4));
+
+ assertEquals(3, message.getInt32ToMessageField().size());
+ assertEquals(111, message.getInt32ToMessageField().get(1).getValue());
+ assertEquals(33, message.getInt32ToMessageField().get(3).getValue());
+ assertEquals(44, message.getInt32ToMessageField().get(4).getValue());
+
+ assertEquals(3, message.getStringToInt32Field().size());
+ assertEquals(111, message.getStringToInt32Field().get("1").intValue());
+ assertEquals(33, message.getStringToInt32Field().get("3").intValue());
+ assertEquals(44, message.getStringToInt32Field().get("4").intValue());
+ }
+
+ private void assertMapValuesCleared(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageField().size());
+ assertEquals(0, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(0, testMapOrBuilder.getStringToInt32Field().size());
+ assertEquals(0, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testGetMapIsImmutable() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+
+ setMapValuesUsingAccessors(builder);
+ assertMapsAreImmutable(builder);
+ assertMapsAreImmutable(builder.build());
+ }
+
+ private void assertMapsAreImmutable(TestMapOrBuilder testMapOrBuilder) {
+ assertImmutable(testMapOrBuilder.getInt32ToInt32Field(), 1, 2);
+ assertImmutable(testMapOrBuilder.getInt32ToStringField(), 1, "2");
+ assertImmutable(testMapOrBuilder.getInt32ToBytesField(), 1, TestUtil.toBytes("2"));
+ assertImmutable(testMapOrBuilder.getInt32ToEnumField(), 1, TestMap.EnumValue.FOO);
+ assertImmutable(
+ testMapOrBuilder.getInt32ToMessageField(), 1, MessageValue.getDefaultInstance());
+ assertImmutable(testMapOrBuilder.getStringToInt32Field(), "1", 2);
+ }
+
+ private <K, V> void assertImmutable(Map<K, V> map, K key, V value) {
+ try {
+ map.put(key, value);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ public void testMutableMapLifecycle() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.put(2, 3);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ builder.getMutableInt32ToInt32Field().put(2, 3);
+ assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field());
+ //
+ Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
+ enumMap.put(1, TestMap.EnumValue.BAR);
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField());
+ try {
+ enumMap.put(2, TestMap.EnumValue.FOO);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField());
+ builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
+ assertEquals(
+ newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO),
+ builder.getInt32ToEnumField());
+ //
+ Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
+ stringMap.put(1, "1");
+ assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField());
+ try {
+ stringMap.put(2, "2");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, "1"), builder.getInt32ToStringField());
+ builder.putInt32ToStringField(2, "2");
+ assertEquals(
+ newMap(1, "1", 2, "2"),
+ builder.getInt32ToStringField());
+ //
+ Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
+ messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.build().getInt32ToMessageField());
+ try {
+ messageMap.put(2, TestMap.MessageValue.getDefaultInstance());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ builder.putInt32ToMessageField(2, TestMap.MessageValue.getDefaultInstance());
+ assertEquals(
+ newMap(1, TestMap.MessageValue.getDefaultInstance(),
+ 2, TestMap.MessageValue.getDefaultInstance()),
+ builder.getInt32ToMessageField());
+ }
+ //
+ public void testMutableMapLifecycle_collections() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ Map<Integer, Integer> intMap = builder.getMutableInt32ToInt32Field();
+ intMap.put(1, 2);
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ try {
+ intMap.remove(2);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.entrySet().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.keySet().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ intMap.values().iterator().remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(newMap(1, 2), intMap);
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field());
+ }
+
+
+ public void testGettersAndSetters() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ TestMap message = builder.build();
+ assertMapValuesCleared(message);
+
+ builder = message.toBuilder();
+ setMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ assertMapValuesCleared(builder);
+ message = builder.build();
+ assertMapValuesCleared(message);
+ }
+
+ public void testPutAll() throws Exception {
+ TestMap.Builder sourceBuilder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(sourceBuilder);
+ TestMap source = sourceBuilder.build();
+ assertMapValuesSet(source);
+
+ TestMap.Builder destination = TestMap.newBuilder();
+ copyMapValues(source, destination);
+ assertMapValuesSet(destination.build());
+ }
+
+ public void testPutAllForUnknownEnumValues() throws Exception {
+ TestMap source = TestMap.newBuilder()
+ .putAllInt32ToEnumFieldValue(newMap(
+ 0, 0,
+ 1, 1,
+ 2, 1000)) // unknown value.
+ .build();
+
+ TestMap destination = TestMap.newBuilder()
+ .putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue())
+ .build();
+
+ assertEquals(0, destination.getInt32ToEnumFieldValue().get(0).intValue());
+ assertEquals(1, destination.getInt32ToEnumFieldValue().get(1).intValue());
+ assertEquals(1000, destination.getInt32ToEnumFieldValue().get(2).intValue());
+ assertEquals(3, destination.getInt32ToEnumFieldCount());
+ }
+
+ public void testPutForUnknownEnumValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putInt32ToEnumFieldValue(0, 0)
+ .putInt32ToEnumFieldValue(1, 1);
+
+ try {
+ builder.putInt32ToEnumFieldValue(2, 1000); // unknown value.
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ TestMap message = builder.build();
+ assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
+ assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
+ assertEquals(2, message.getInt32ToEnumFieldCount());
+ }
+
+ public void testPutChecksNullKeysAndValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putInt32ToMessageField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+
+ try {
+ builder.putStringToInt32Field(null, 1);
+ fail();
+ } catch (NullPointerException e) {
+ // expected.
+ }
+ }
+
+ public void testSerializeAndParse() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesSet(message);
+
+ builder = message.toBuilder();
+ updateMapValuesUsingAccessors(builder);
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesUpdated(message);
+
+ builder = message.toBuilder();
+ builder.clear();
+ message = builder.build();
+ assertEquals(message.getSerializedSize(), message.toByteString().size());
+ message = TestMap.parser().parseFrom(message.toByteString());
+ assertMapValuesCleared(message);
+ }
+
+ private TestMap tryParseTestMap(BizarroTestMap bizarroMap) throws IOException {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ bizarroMap.writeTo(output);
+ output.flush();
+ return TestMap.parser().parseFrom(ByteString.copyFrom(byteArrayOutputStream.toByteArray()));
+ }
+
+ public void testParseError() throws Exception {
+ ByteString bytes = TestUtil.toBytes("SOME BYTES");
+ String stringKey = "a string key";
+
+ TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToInt32Field(5, bytes)
+ .build());
+ assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToStringField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToBytesField(stringKey, 5)
+ .build());
+ assertEquals(map.getInt32ToBytesFieldOrDefault(0, null), ByteString.EMPTY);
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToEnumField(stringKey, bytes)
+ .build());
+ assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+
+ try {
+ tryParseTestMap(BizarroTestMap.newBuilder()
+ .putInt32ToMessageField(stringKey, bytes)
+ .build());
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ assertTrue(expected.getUnfinishedMessage() instanceof TestMap);
+ map = (TestMap) expected.getUnfinishedMessage();
+ assertTrue(map.getInt32ToMessageField().isEmpty());
+ }
+
+ map = tryParseTestMap(BizarroTestMap.newBuilder()
+ .putStringToInt32Field(stringKey, bytes)
+ .build());
+ assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ TestMap.Builder other = TestMap.newBuilder();
+ other.mergeFrom(message);
+ assertMapValuesSet(other.build());
+ }
+
+ public void testEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We can't control the order of elements in a HashMap. The best we can do
+ // here is to add elements in different order.
+ TestMap.Builder b1 = TestMap.newBuilder()
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4)
+ .putInt32ToInt32Field(5, 6);
+ TestMap m1 = b1.build();
+
+ TestMap.Builder b2 = TestMap.newBuilder()
+ .putInt32ToInt32Field(5, 6)
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4);
+ TestMap m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.putInt32ToInt32Field(1, 0);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+
+ // Regression test for b/18549190: if a map is a subset of the other map,
+ // equals() should return false.
+ b2.removeInt32ToInt32Field(1);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ assertFalse(m2.equals(m1));
+ }
+
+ public void testNestedBuilderOnChangeEventPropagation() {
+ TestOnChangeEventPropagation.Builder parent =
+ TestOnChangeEventPropagation.newBuilder();
+ parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 2);
+ TestOnChangeEventPropagation message = parent.build();
+ assertEquals(2, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make a change using nested builder.
+ parent.getOptionalMessageBuilder().putInt32ToInt32Field(1, 3);
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(3, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make another change using mergeFrom()
+ TestMap.Builder other = TestMap.newBuilder().putInt32ToInt32Field(1, 4);
+ parent.getOptionalMessageBuilder().mergeFrom(other.build());
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(4, message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Make yet another change by clearing the nested builder.
+ parent.getOptionalMessageBuilder().clear();
+
+ // Should be able to observe the change.
+ message = parent.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
+ public void testNestedBuilderOnChangeEventPropagationReflection() {
+ FieldDescriptor intMapField = f("int32_to_int32_field");
+ // Create an outer message builder with nested builder.
+ TestOnChangeEventPropagation.Builder parentBuilder =
+ TestOnChangeEventPropagation.newBuilder();
+ TestMap.Builder testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+
+ // Create a map entry message.
+ TestMap.Builder entryBuilder = TestMap.newBuilder().putInt32ToInt32Field(1, 1);
+
+ // Put the entry into the nested builder.
+ testMapBuilder.addRepeatedField(
+ intMapField, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ TestOnChangeEventPropagation message = parentBuilder.build();
+ assertEquals(1, message.getOptionalMessage().getInt32ToInt32Field().size());
+
+ // Change the entry value.
+ entryBuilder.putInt32ToInt32Field(1, 4);
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.setRepeatedField(
+ intMapField, 0, entryBuilder.getRepeatedField(intMapField, 0));
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(4,
+ message.getOptionalMessage().getInt32ToInt32Field().get(1).intValue());
+
+ // Clear the nested builder.
+ testMapBuilder = parentBuilder.getOptionalMessageBuilder();
+ testMapBuilder.clearField(intMapField);
+
+ // Should be able to observe the change.
+ message = parentBuilder.build();
+ assertEquals(0, message.getOptionalMessage().getInt32ToInt32Field().size());
+ }
+
+ // The following methods are used to test reflection API.
+
+ private static FieldDescriptor f(String name) {
+ return TestMap.getDescriptor().findFieldByName(name);
+ }
+
+ private static Object getFieldValue(Message mapEntry, String name) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ return mapEntry.getField(field);
+ }
+
+ private static Message.Builder setFieldValue(
+ Message.Builder mapEntry, String name, Object value) {
+ FieldDescriptor field = mapEntry.getDescriptorForType().findFieldByName(name);
+ mapEntry.setField(field, value);
+ return mapEntry;
+ }
+
+ private static void assertHasMapValues(Message message, String name, Map<?, ?> values) {
+ FieldDescriptor field = f(name);
+ for (Object entry : (List<?>) message.getField(field)) {
+ Message mapEntry = (Message) entry;
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ assertEquals(values.size(), message.getRepeatedFieldCount(field));
+ for (int i = 0; i < message.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) message.getRepeatedField(field, i);
+ Object key = getFieldValue(mapEntry, "key");
+ Object value = getFieldValue(mapEntry, "value");
+ assertTrue(values.containsKey(key));
+ assertEquals(value, values.get(key));
+ }
+ }
+
+ private static <KeyType, ValueType>
+ Message newMapEntry(Message.Builder builder, String name, KeyType key, ValueType value) {
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ FieldDescriptor keyField = entryBuilder.getDescriptorForType().findFieldByName("key");
+ FieldDescriptor valueField = entryBuilder.getDescriptorForType().findFieldByName("value");
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ return entryBuilder.build();
+ }
+
+ private static void setMapValues(Message.Builder builder, String name, Map<?, ?> values) {
+ List<Message> entryList = new ArrayList<Message>();
+ for (Map.Entry<?, ?> entry : values.entrySet()) {
+ entryList.add(newMapEntry(builder, name, entry.getKey(), entry.getValue()));
+ }
+ FieldDescriptor field = builder.getDescriptorForType().findFieldByName(name);
+ builder.setField(field, entryList);
+ }
+
+ private static <KeyType, ValueType>
+ Map<KeyType, ValueType> mapForValues(
+ KeyType key1, ValueType value1, KeyType key2, ValueType value2) {
+ Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testReflectionApi() throws Exception {
+ // In reflection API, map fields are just repeated message fields.
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putInt32ToInt32Field(1, 2)
+ .putInt32ToInt32Field(3, 4)
+ .putInt32ToMessageField(11, MessageValue.newBuilder().setValue(22).build())
+ .putInt32ToMessageField(33, MessageValue.newBuilder().setValue(44).build());
+ TestMap message = builder.build();
+
+ // Test getField(), getRepeatedFieldCount(), getRepeatedField().
+ assertHasMapValues(message, "int32_to_int32_field",
+ mapForValues(1, 2, 3, 4));
+ assertHasMapValues(message, "int32_to_message_field",
+ mapForValues(
+ 11, MessageValue.newBuilder().setValue(22).build(),
+ 33, MessageValue.newBuilder().setValue(44).build()));
+
+ // Test clearField()
+ builder.clearField(f("int32_to_int32_field"));
+ builder.clearField(f("int32_to_message_field"));
+ message = builder.build();
+ assertEquals(0, message.getInt32ToInt32Field().size());
+ assertEquals(0, message.getInt32ToMessageField().size());
+
+ // Test setField()
+ setMapValues(builder, "int32_to_int32_field",
+ mapForValues(11, 22, 33, 44));
+ setMapValues(builder, "int32_to_message_field",
+ mapForValues(
+ 111, MessageValue.newBuilder().setValue(222).build(),
+ 333, MessageValue.newBuilder().setValue(444).build()));
+ message = builder.build();
+ assertEquals(22, message.getInt32ToInt32Field().get(11).intValue());
+ assertEquals(44, message.getInt32ToInt32Field().get(33).intValue());
+ assertEquals(222, message.getInt32ToMessageField().get(111).getValue());
+ assertEquals(444, message.getInt32ToMessageField().get(333).getValue());
+
+ // Test addRepeatedField
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 66));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(666).build()));
+ message = builder.build();
+ assertEquals(66, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(666, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test addRepeatedField (overriding existing values)
+ builder.addRepeatedField(f("int32_to_int32_field"),
+ newMapEntry(builder, "int32_to_int32_field", 55, 55));
+ builder.addRepeatedField(f("int32_to_message_field"),
+ newMapEntry(builder, "int32_to_message_field", 555,
+ MessageValue.newBuilder().setValue(555).build()));
+ message = builder.build();
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ assertEquals(555, message.getInt32ToMessageField().get(555).getValue());
+
+ // Test setRepeatedField
+ for (int i = 0; i < builder.getRepeatedFieldCount(f("int32_to_int32_field")); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(f("int32_to_int32_field"), i);
+ int oldKey = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int oldValue = ((Integer) getFieldValue(mapEntry, "value")).intValue();
+ // Swap key with value for each entry.
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ setFieldValue(mapEntryBuilder, "key", oldValue);
+ setFieldValue(mapEntryBuilder, "value", oldKey);
+ builder.setRepeatedField(f("int32_to_int32_field"), i, mapEntryBuilder.build());
+ }
+ message = builder.build();
+ assertEquals(11, message.getInt32ToInt32Field().get(22).intValue());
+ assertEquals(33, message.getInt32ToInt32Field().get(44).intValue());
+ assertEquals(55, message.getInt32ToInt32Field().get(55).intValue());
+ }
+
+ public void testTextFormat() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ String textData = TextFormat.printToString(message);
+
+ builder = TestMap.newBuilder();
+ TextFormat.merge(textData, builder);
+ message = builder.build();
+
+ assertMapValuesSet(message);
+ }
+
+ public void testDynamicMessage() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ Message dynamicMessage = dynamicDefaultInstance
+ .newBuilderForType().mergeFrom(message.toByteString()).build();
+
+ assertEquals(message, dynamicMessage);
+ assertEquals(message.hashCode(), dynamicMessage.hashCode());
+ }
+
+ public void testReflectionEqualsAndHashCode() throws Exception {
+ // Test that generated equals() and hashCode() will disregard the order
+ // of map entries when comparing/hashing map fields.
+
+ // We use DynamicMessage to test reflection based equals()/hashCode().
+ Message dynamicDefaultInstance =
+ DynamicMessage.getDefaultInstance(TestMap.getDescriptor());
+ FieldDescriptor field = f("int32_to_int32_field");
+
+ Message.Builder b1 = dynamicDefaultInstance.newBuilderForType();
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 1, 2));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 3, 4));
+ b1.addRepeatedField(field, newMapEntry(b1, "int32_to_int32_field", 5, 6));
+ Message m1 = b1.build();
+
+ Message.Builder b2 = dynamicDefaultInstance.newBuilderForType();
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 5, 6));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 1, 2));
+ b2.addRepeatedField(field, newMapEntry(b2, "int32_to_int32_field", 3, 4));
+ Message m2 = b2.build();
+
+ assertEquals(m1, m2);
+ assertEquals(m1.hashCode(), m2.hashCode());
+
+ // Make sure we did compare map fields.
+ b2.setRepeatedField(field, 0, newMapEntry(b1, "int32_to_int32_field", 0, 0));
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ // Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
+ // to be different.
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putAllInt32ToEnumFieldValue(newMap(
+ 0, 0,
+ 1, 1,
+ 2, 1000)); // unknown value.
+ TestMap message = builder.build();
+
+ assertEquals(TestMap.EnumValue.FOO,
+ message.getInt32ToEnumField().get(0));
+ assertEquals(TestMap.EnumValue.BAR,
+ message.getInt32ToEnumField().get(1));
+ assertEquals(TestMap.EnumValue.UNRECOGNIZED,
+ message.getInt32ToEnumField().get(2));
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // Unknown enum values should be preserved after:
+ // 1. Serialization and parsing.
+ // 2. toBuild().
+ // 3. mergeFrom().
+ message = TestMap.parseFrom(message.toByteString());
+ assertEquals(1000, message.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = message.toBuilder();
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+ builder = TestMap.newBuilder().mergeFrom(message);
+ assertEquals(1000, builder.getInt32ToEnumFieldValue().get(2).intValue());
+
+ // hashCode()/equals() should take unknown enum values into account.
+ builder.putAllInt32ToEnumFieldValue(newMap(2, 1001));
+ TestMap message2 = builder.build();
+ assertFalse(message.hashCode() == message2.hashCode());
+ assertFalse(message.equals(message2));
+ // Unknown values will be converted to UNRECOGNIZED so the resulted enum map
+ // should be the same.
+ assertTrue(message.getInt32ToEnumField().equals(message2.getInt32ToEnumField()));
+ }
+
+ public void testUnknownEnumValuesInReflectionApi() throws Exception {
+ Descriptor descriptor = TestMap.getDescriptor();
+ EnumDescriptor enumDescriptor = TestMap.EnumValue.getDescriptor();
+ FieldDescriptor field = descriptor.findFieldByName("int32_to_enum_field");
+
+ Map<Integer, Integer> data = newMap(
+ 0, 0,
+ 1, 1,
+ 2, 1000); // unknown value
+
+ TestMap.Builder builder = TestMap.newBuilder()
+ .putAllInt32ToEnumFieldValue(data);
+
+ // Try to read unknown enum values using reflection API.
+ for (int i = 0; i < builder.getRepeatedFieldCount(field); i++) {
+ Message mapEntry = (Message) builder.getRepeatedField(field, i);
+ int key = ((Integer) getFieldValue(mapEntry, "key")).intValue();
+ int value = ((EnumValueDescriptor) getFieldValue(mapEntry, "value")).getNumber();
+ assertEquals(data.get(key).intValue(), value);
+ Message.Builder mapEntryBuilder = mapEntry.toBuilder();
+ // Increase the value by 1.
+ setFieldValue(mapEntryBuilder, "value",
+ enumDescriptor.findValueByNumberCreatingIfUnknown(value + 1));
+ builder.setRepeatedField(field, i, mapEntryBuilder.build());
+ }
+
+ // Verify that enum values have been successfully updated.
+ TestMap message = builder.build();
+ for (Map.Entry<Integer, Integer> entry : message.getInt32ToEnumFieldValue().entrySet()) {
+ assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue());
+ }
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+
+ assertEquals(Arrays.asList("1", "2", "3"),
+ new ArrayList<String>(message.getStringToInt32Field().keySet()));
+ }
+
+ public void testGetMap() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ TestMap message = builder.build();
+ assertEquals(
+ message.getStringToInt32Field(),
+ message.getStringToInt32FieldMap());
+ assertEquals(
+ message.getInt32ToBytesField(),
+ message.getInt32ToBytesFieldMap());
+ assertEquals(
+ message.getInt32ToEnumField(),
+ message.getInt32ToEnumFieldMap());
+ assertEquals(
+ message.getInt32ToEnumFieldValue(),
+ message.getInt32ToEnumFieldValueMap());
+ assertEquals(
+ message.getInt32ToMessageField(),
+ message.getInt32ToMessageFieldMap());
+ }
+
+ public void testContains() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ assertMapContainsSetValues(builder);
+ assertMapContainsSetValues(builder.build());
+ }
+
+ private void assertMapContainsSetValues(TestMapOrBuilder testMapOrBuilder) {
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(1));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(2));
+ assertTrue(testMapOrBuilder.containsInt32ToInt32Field(3));
+ assertFalse(testMapOrBuilder.containsInt32ToInt32Field(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToStringField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToStringField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToBytesField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToBytesField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToEnumField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToEnumField(-1));
+
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(1));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(2));
+ assertTrue(testMapOrBuilder.containsInt32ToMessageField(3));
+ assertFalse(testMapOrBuilder.containsInt32ToMessageField(-1));
+
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("1"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("2"));
+ assertTrue(testMapOrBuilder.containsStringToInt32Field("3"));
+ assertFalse(testMapOrBuilder.containsStringToInt32Field("-1"));
+ }
+
+ public void testCount() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+
+ setMapValuesUsingAccessors(builder);
+ assertMapCounts(3, builder);
+
+ TestMap message = builder.build();
+ assertMapCounts(3, message);
+
+ builder = message.toBuilder().putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ assertEquals(4, builder.build().getInt32ToInt32FieldCount());
+
+ // already present - should be unchanged
+ builder.putInt32ToInt32Field(4, 44);
+ assertEquals(4, builder.getInt32ToInt32FieldCount());
+ }
+
+ private void assertMapCounts(int expectedCount, TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToInt32FieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToStringFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToBytesFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToEnumFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getInt32ToMessageFieldCount());
+ assertEquals(expectedCount, testMapOrBuilder.getStringToInt32FieldCount());
+ }
+
+ public void testGetOrDefault() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValuesUsingAccessors(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrDefault(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(1, -11));
+ assertEquals(-11, testMapOrBuilder.getInt32ToInt32FieldOrDefault(-1, -11));
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrDefault(1, "-11"));
+ assertNull("-11", testMapOrBuilder.getInt32ToStringFieldOrDefault(-1, null));
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToBytesFieldOrDefault(-1, null));
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToEnumFieldOrDefault(-1, null));
+
+ assertEquals(
+ TestMap.EnumValue.BAR.getNumber(),
+ (int) testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(2, -1));
+ assertEquals(-1, testMapOrBuilder.getInt32ToEnumFieldValueOrDefault(-1000, -1));
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrDefault(1, null));
+ assertNull(testMapOrBuilder.getInt32ToMessageFieldOrDefault(-1, null));
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrDefault("1", -11));
+ assertEquals(-11, testMapOrBuilder.getStringToInt32FieldOrDefault("-1", -11));
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrDefault(null, -11);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testGetOrThrow() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ assertMapCounts(0, builder);
+ setMapValuesUsingAccessors(builder);
+ doTestGetOrDefault(builder);
+ doTestGetOrDefault(builder.build());
+ }
+
+ public void doTestGetOrThrow(TestMapOrBuilder testMapOrBuilder) {
+ assertEquals(11, testMapOrBuilder.getInt32ToInt32FieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToInt32FieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals("11", testMapOrBuilder.getInt32ToStringFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToStringFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestUtil.toBytes("11"), testMapOrBuilder.getInt32ToBytesFieldOrThrow(1));
+
+ try {
+ testMapOrBuilder.getInt32ToBytesFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, testMapOrBuilder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToEnumFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(
+ TestMap.EnumValue.BAR.getNumber(), testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(2));
+ try {
+ testMapOrBuilder.getInt32ToEnumFieldValueOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(MessageValue.newBuilder().setValue(11).build(),
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(1));
+ try {
+ testMapOrBuilder.getInt32ToMessageFieldOrThrow(-1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ assertEquals(11, testMapOrBuilder.getStringToInt32FieldOrThrow("1"));
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow("-1");
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ testMapOrBuilder.getStringToInt32FieldOrThrow(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPut() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.putInt32ToInt32Field(1, 11);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+
+ builder.putInt32ToStringField(1, "a");
+ assertEquals("a", builder.getInt32ToStringFieldOrThrow(1));
+ try {
+ builder.putInt32ToStringField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToBytesField(1, TestUtil.toBytes("11"));
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ try {
+ builder.putInt32ToBytesField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToEnumField(1, TestMap.EnumValue.FOO);
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ try {
+ builder.putInt32ToEnumField(1, null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ builder.putInt32ToEnumFieldValue(1, TestMap.EnumValue.BAR.getNumber());
+ assertEquals(
+ TestMap.EnumValue.BAR.getNumber(), builder.getInt32ToEnumFieldValueOrThrow(1));
+ try {
+ builder.putInt32ToEnumFieldValue(1, -1);
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ builder.putStringToInt32Field("a", 1);
+ assertEquals(1, builder.getStringToInt32FieldOrThrow("a"));
+ try {
+ builder.putStringToInt32Field(null, -1);
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testRemove() {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValuesUsingAccessors(builder);
+ assertEquals(11, builder.getInt32ToInt32FieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToInt32Field(1);
+ assertEquals(-1, builder.getInt32ToInt32FieldOrDefault(1, -1));
+ }
+
+ assertEquals("11", builder.getInt32ToStringFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToStringField(1);
+ assertNull(builder.getInt32ToStringFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestUtil.toBytes("11"), builder.getInt32ToBytesFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToBytesField(1);
+ assertNull(builder.getInt32ToBytesFieldOrDefault(1, null));
+ }
+
+ assertEquals(TestMap.EnumValue.FOO, builder.getInt32ToEnumFieldOrThrow(1));
+ for (int times = 0; times < 2; times++) {
+ builder.removeInt32ToEnumField(1);
+ assertNull(builder.getInt32ToEnumFieldOrDefault(1, null));
+ }
+
+ assertEquals(11, builder.getStringToInt32FieldOrThrow("1"));
+ for (int times = 0; times < 2; times++) {
+ builder.removeStringToInt32Field("1");
+ assertEquals(-1, builder.getStringToInt32FieldOrDefault("1", -1));
+ }
+
+ try {
+ builder.removeStringToInt32Field(null);
+ fail();
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testReservedWordsFieldNames() {
+ ReservedAsMapField.newBuilder().build();
+ ReservedAsMapFieldWithEnumValue.newBuilder().build();
+ }
+
+ public void testDeterministicSerialziation() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ // int32->int32
+ builder.putInt32ToInt32Field(5, 1);
+ builder.putInt32ToInt32Field(1, 1);
+ builder.putInt32ToInt32Field(4, 1);
+ builder.putInt32ToInt32Field(-2, 1);
+ builder.putInt32ToInt32Field(0, 1);
+
+ // uint32->int32
+ builder.putUint32ToInt32Field(5, 1);
+ builder.putUint32ToInt32Field(1, 1);
+ builder.putUint32ToInt32Field(4, 1);
+ builder.putUint32ToInt32Field(-2, 1);
+ builder.putUint32ToInt32Field(0, 1);
+
+ // int64->int32
+ builder.putInt64ToInt32Field(5L, 1);
+ builder.putInt64ToInt32Field(1L, 1);
+ builder.putInt64ToInt32Field(4L, 1);
+ builder.putInt64ToInt32Field(-2L, 1);
+ builder.putInt64ToInt32Field(0L, 1);
+
+ // string->int32
+ builder.putStringToInt32Field("baz", 1);
+ builder.putStringToInt32Field("foo", 1);
+ builder.putStringToInt32Field("bar", 1);
+ builder.putStringToInt32Field("", 1);
+ builder.putStringToInt32Field("hello", 1);
+ builder.putStringToInt32Field("world", 1);
+
+ TestMap message = builder.build();
+ byte[] serialized = new byte[message.getSerializedSize()];
+ CodedOutputStream output = CodedOutputStream.newInstance(serialized);
+ output.useDeterministicSerialization();
+ message.writeTo(output);
+ output.flush();
+
+ CodedInputStream input = CodedInputStream.newInstance(serialized);
+ List<Integer> int32Keys = new ArrayList<Integer>();
+ List<Integer> uint32Keys = new ArrayList<Integer>();
+ List<Long> int64Keys = new ArrayList<Long>();
+ List<String> stringKeys = new ArrayList<String>();
+ int tag;
+ while (true) {
+ tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+ int length = input.readRawVarint32();
+ int oldLimit = input.pushLimit(length);
+ switch (WireFormat.getTagFieldNumber(tag)) {
+ case TestMap.STRING_TO_INT32_FIELD_FIELD_NUMBER:
+ stringKeys.add(readMapStringKey(input));
+ break;
+ case TestMap.INT32_TO_INT32_FIELD_FIELD_NUMBER:
+ int32Keys.add(readMapIntegerKey(input));
+ break;
+ case TestMap.UINT32_TO_INT32_FIELD_FIELD_NUMBER:
+ uint32Keys.add(readMapIntegerKey(input));
+ break;
+ case TestMap.INT64_TO_INT32_FIELD_FIELD_NUMBER:
+ int64Keys.add(readMapLongKey(input));
+ break;
+ default:
+ fail("Unexpected fields.");
+ }
+ input.popLimit(oldLimit);
+ }
+ assertEquals(
+ Arrays.asList(-2, 0, 1, 4, 5),
+ int32Keys);
+ assertEquals(
+ Arrays.asList(-2, 0, 1, 4, 5),
+ uint32Keys);
+ assertEquals(
+ Arrays.asList(-2L, 0L, 1L, 4L, 5L),
+ int64Keys);
+ assertEquals(
+ Arrays.asList("", "bar", "baz", "foo", "hello", "world"),
+ stringKeys);
+ }
+
+ public void testInitFromPartialDynamicMessage() {
+ FieldDescriptor fieldDescriptor =
+ TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
+ Descriptor mapEntryType = fieldDescriptor.getMessageType();
+ FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
+ FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
+ DynamicMessage dynamicMessage =
+ DynamicMessage.newBuilder(TestMap.getDescriptor())
+ .addRepeatedField(
+ fieldDescriptor,
+ DynamicMessage.newBuilder(mapEntryType)
+ .setField(keyField, 10)
+ .setField(valueField, TestMap.MessageValue.newBuilder().setValue(10).build())
+ .build())
+ .build();
+ TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
+ assertEquals(
+ TestMap.MessageValue.newBuilder().setValue(10).build(),
+ message.getInt32ToMessageFieldMap().get(10));
+ }
+
+ public void testInitFromFullyDynamicMessage() {
+ FieldDescriptor fieldDescriptor =
+ TestMap.getDescriptor().findFieldByNumber(TestMap.INT32_TO_MESSAGE_FIELD_FIELD_NUMBER);
+ Descriptor mapEntryType = fieldDescriptor.getMessageType();
+ FieldDescriptor keyField = mapEntryType.findFieldByNumber(1);
+ FieldDescriptor valueField = mapEntryType.findFieldByNumber(2);
+ DynamicMessage dynamicMessage =
+ DynamicMessage.newBuilder(TestMap.getDescriptor())
+ .addRepeatedField(
+ fieldDescriptor,
+ DynamicMessage.newBuilder(mapEntryType)
+ .setField(keyField, 10)
+ .setField(
+ valueField,
+ DynamicMessage.newBuilder(TestMap.MessageValue.getDescriptor())
+ .setField(
+ TestMap.MessageValue.getDescriptor().findFieldByName("value"), 10)
+ .build())
+ .build())
+ .build();
+ TestMap message = TestMap.newBuilder().mergeFrom(dynamicMessage).build();
+ assertEquals(
+ TestMap.MessageValue.newBuilder().setValue(10).build(),
+ message.getInt32ToMessageFieldMap().get(10));
+ }
+
+ private int readMapIntegerKey(CodedInputStream input) throws IOException {
+ int tag = input.readTag();
+ assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
+ int ret = input.readInt32();
+ // skip the value field.
+ input.skipField(input.readTag());
+ assertTrue(input.isAtEnd());
+ return ret;
+ }
+
+ private long readMapLongKey(CodedInputStream input) throws IOException {
+ int tag = input.readTag();
+ assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_VARINT), tag);
+ long ret = input.readInt64();
+ // skip the value field.
+ input.skipField(input.readTag());
+ assertTrue(input.isAtEnd());
+ return ret;
+ }
+
+ private String readMapStringKey(CodedInputStream input) throws IOException {
+ int tag = input.readTag();
+ assertEquals(WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), tag);
+ String ret = input.readString();
+ // skip the value field.
+ input.skipField(input.readTag());
+ assertTrue(input.isAtEnd());
+ return ret;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2, K key3, V value3) {
+ Map<K, V> map = new HashMap<K, V>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ map.put(key3, value3);
+ return map;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MessageTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MessageTest.java
new file mode 100644
index 0000000000..75b79a34e2
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/MessageTest.java
@@ -0,0 +1,351 @@
+// 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 protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestRequiredForeign;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Misc. unit tests for message operations that apply to both generated
+ * and dynamic messages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class MessageTest extends TestCase {
+ // =================================================================
+ // Message-merging tests.
+
+ static final TestAllTypes MERGE_SOURCE =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .build();
+
+ static final TestAllTypes MERGE_DEST =
+ TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .setOptionalForeignMessage(ForeignMessage.newBuilder().setC(3).build())
+ .addRepeatedString("qux")
+ .build();
+
+ static final String MERGE_RESULT_TEXT =
+ "optional_int32: 1\n" +
+ "optional_int64: 2\n" +
+ "optional_string: \"foo\"\n" +
+ "optional_foreign_message {\n" +
+ " c: 3\n" +
+ "}\n" +
+ "repeated_string: \"qux\"\n" +
+ "repeated_string: \"bar\"\n";
+
+ public void testMergeFrom() throws Exception {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(MERGE_SOURCE).build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /**
+ * Test merging a DynamicMessage into a GeneratedMessage. As long as they
+ * have the same descriptor, this should work, but it is an entirely different
+ * code path.
+ */
+ public void testMergeFromDynamic() throws Exception {
+ TestAllTypes result =
+ TestAllTypes.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ /** Test merging two DynamicMessages. */
+ public void testDynamicMergeFrom() throws Exception {
+ DynamicMessage result =
+ DynamicMessage.newBuilder(MERGE_DEST)
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertEquals(MERGE_RESULT_TEXT, result.toString());
+ }
+
+ // =================================================================
+ // Required-field-related tests.
+
+ private static final TestRequired TEST_REQUIRED_UNINITIALIZED =
+ TestRequired.getDefaultInstance();
+ private static final TestRequired TEST_REQUIRED_INITIALIZED =
+ TestRequired.newBuilder().setA(1).setB(2).setC(3).build();
+
+ public void testRequired() throws Exception {
+ TestRequired.Builder builder = TestRequired.newBuilder();
+
+ assertFalse(builder.isInitialized());
+ builder.setA(1);
+ assertFalse(builder.isInitialized());
+ builder.setB(1);
+ assertFalse(builder.isInitialized());
+ builder.setC(1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredForeign() throws Exception {
+ TestRequiredForeign.Builder builder = TestRequiredForeign.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setOptionalMessage(TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedMessage(0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredExtension() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+
+ assertTrue(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.single, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addExtension(TestRequired.multi, TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setExtension(TestRequired.multi, 0, TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamic() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("a"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("b"), 1);
+ assertFalse(builder.isInitialized());
+ builder.setField(descriptor.findFieldByName("c"), 1);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testRequiredDynamicForeign() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequiredForeign.getDescriptor();
+ DynamicMessage.Builder builder = DynamicMessage.newBuilder(descriptor);
+
+ assertTrue(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setField(descriptor.findFieldByName("optional_message"),
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+
+ builder.addRepeatedField(descriptor.findFieldByName("repeated_message"),
+ TEST_REQUIRED_UNINITIALIZED);
+ assertFalse(builder.isInitialized());
+
+ builder.setRepeatedField(descriptor.findFieldByName("repeated_message"), 0,
+ TEST_REQUIRED_INITIALIZED);
+ assertTrue(builder.isInitialized());
+ }
+
+ public void testUninitializedException() throws Exception {
+ try {
+ TestRequired.newBuilder().build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequired message = TestRequired.newBuilder().buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testNestedUninitializedException() throws Exception {
+ try {
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testBuildNestedPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ TestRequiredForeign message =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testParseUnititialized() throws Exception {
+ try {
+ TestRequired.parseFrom(ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testParseNestedUnititialized() throws Exception {
+ ByteString data =
+ TestRequiredForeign.newBuilder()
+ .setOptionalMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .addRepeatedMessage(TEST_REQUIRED_UNINITIALIZED)
+ .buildPartial().toByteString();
+
+ try {
+ TestRequiredForeign.parseFrom(data);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals(
+ "Message missing required fields: " +
+ "optional_message.a, " +
+ "optional_message.b, " +
+ "optional_message.c, " +
+ "repeated_message[0].a, " +
+ "repeated_message[0].b, " +
+ "repeated_message[0].c, " +
+ "repeated_message[1].a, " +
+ "repeated_message[1].b, " +
+ "repeated_message[1].c",
+ e.getMessage());
+ }
+ }
+
+ public void testDynamicUninitializedException() throws Exception {
+ try {
+ DynamicMessage.newBuilder(TestRequired.getDescriptor()).build();
+ fail("Should have thrown an exception.");
+ } catch (UninitializedMessageException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ public void testDynamicBuildPartial() throws Exception {
+ // We're mostly testing that no exception is thrown.
+ DynamicMessage message =
+ DynamicMessage.newBuilder(TestRequired.getDescriptor())
+ .buildPartial();
+ assertFalse(message.isInitialized());
+ }
+
+ public void testDynamicParseUnititialized() throws Exception {
+ try {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage.parseFrom(descriptor, ByteString.EMPTY);
+ fail("Should have thrown an exception.");
+ } catch (InvalidProtocolBufferException e) {
+ assertEquals("Message missing required fields: a, b, c", e.getMessage());
+ }
+ }
+
+ /** Test reading unset repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNull() throws Exception {
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(MERGE_SOURCE).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 0);
+ }
+
+ /** Test reading repeated message from DynamicMessage. */
+ public void testDynamicRepeatedMessageNotNull() throws Exception {
+
+ TestAllTypes REPEATED_NESTED =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .setOptionalForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedString("bar")
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .addRepeatedForeignMessage(ForeignMessage.getDefaultInstance())
+ .build();
+ Descriptors.Descriptor descriptor = TestRequired.getDescriptor();
+ DynamicMessage result =
+ DynamicMessage.newBuilder(TestAllTypes.getDescriptor())
+ .mergeFrom(DynamicMessage.newBuilder(REPEATED_NESTED).build())
+ .build();
+
+ assertTrue(result.getField(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")) instanceof List<?>);
+ assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
+ .findFieldByName("repeated_foreign_message")), 2);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
new file mode 100644
index 0000000000..03ed65a550
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
@@ -0,0 +1,183 @@
+// 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 protobuf_unittest.Vehicle;
+import protobuf_unittest.Wheel;
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Test cases that exercise end-to-end use cases involving
+ * {@link SingleFieldBuilder} and {@link RepeatedFieldBuilder}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class NestedBuildersTest extends TestCase {
+
+ public void testMessagesAndBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(3);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(4)
+ .setWidth(4);
+ vehicleBuilder.getEngineBuilder()
+ .setLiters(10);
+
+ Vehicle vehicle = vehicleBuilder.build();
+ assertEquals(4, vehicle.getWheelCount());
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(4, wheel.getRadius());
+ assertEquals(i + 1, wheel.getWidth());
+ }
+ assertEquals(10, vehicle.getEngine().getLiters());
+
+ for (int i = 0; i < 4; i++) {
+ vehicleBuilder.getWheelBuilder(i)
+ .setRadius(5)
+ .setWidth(i + 10);
+ }
+ vehicleBuilder.getEngineBuilder().setLiters(20);
+
+ vehicle = vehicleBuilder.build();
+ for (int i = 0; i < 4; i++) {
+ Wheel wheel = vehicle.getWheel(i);
+ assertEquals(5, wheel.getRadius());
+ assertEquals(i + 10, wheel.getWidth());
+ }
+ assertEquals(20, vehicle.getEngine().getLiters());
+ assertTrue(vehicle.hasEngine());
+ }
+
+ public void testMessagesAreCached() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(2);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(3)
+ .setWidth(4);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(5)
+ .setWidth(6);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(7)
+ .setWidth(8);
+
+ // Make sure messages are cached.
+ List<Wheel> wheels = new ArrayList<Wheel>(vehicleBuilder.getWheelList());
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Now get builders and check they didn't change.
+ for (int i = 0; i < wheels.size(); i++) {
+ vehicleBuilder.getWheel(i);
+ }
+ for (int i = 0; i < wheels.size(); i++) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+
+ // Change just one
+ vehicleBuilder.getWheelBuilder(3)
+ .setRadius(20).setWidth(20);
+
+ // Now get wheels and check that only that one changed
+ for (int i = 0; i < wheels.size(); i++) {
+ if (i < 3) {
+ assertSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ } else {
+ assertNotSame(wheels.get(i), vehicleBuilder.getWheel(i));
+ }
+ }
+ }
+
+ public void testRemove_WithNestedBuilders() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(1)
+ .setWidth(1);
+ vehicleBuilder.addWheelBuilder()
+ .setRadius(2)
+ .setWidth(2);
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testRemove_WithNestedMessages() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(1)
+ .setWidth(1));
+ vehicleBuilder.addWheel(Wheel.newBuilder()
+ .setRadius(2)
+ .setWidth(2));
+ vehicleBuilder.removeWheel(0);
+
+ assertEquals(1, vehicleBuilder.getWheelCount());
+ assertEquals(2, vehicleBuilder.getWheel(0).getRadius());
+ }
+
+ public void testMerge() {
+ Vehicle vehicle1 = Vehicle.newBuilder()
+ .addWheel(Wheel.newBuilder().setRadius(1).build())
+ .addWheel(Wheel.newBuilder().setRadius(2).build())
+ .build();
+
+ Vehicle vehicle2 = Vehicle.newBuilder()
+ .mergeFrom(vehicle1)
+ .build();
+ // List should be the same -- no allocation
+ assertSame(vehicle1.getWheelList(), vehicle2.getWheelList());
+
+ Vehicle vehicle3 = vehicle1.toBuilder().build();
+ assertSame(vehicle1.getWheelList(), vehicle3.getWheelList());
+ }
+
+ public void testGettingBuilderMarksFieldAsHaving() {
+ Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
+ vehicleBuilder.getEngineBuilder();
+ Vehicle vehicle = vehicleBuilder.buildPartial();
+ assertTrue(vehicle.hasEngine());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
new file mode 100644
index 0000000000..c388bd0561
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/NioByteStringTest.java
@@ -0,0 +1,619 @@
+// 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 static com.google.protobuf.Internal.UTF_8;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.NoSuchElementException;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link NioByteString}.
+ */
+public class NioByteStringTest extends TestCase {
+ 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 = ByteString.wrap(BYTES).hashCode();
+
+ private final ByteBuffer backingBuffer = ByteBuffer.wrap(BYTES.clone());
+ private final ByteString testString = new NioByteString(backingBuffer);
+
+ public void testExpectedType() {
+ String actualClassName = getActualClassName(testString);
+ assertEquals(CLASSNAME + " should match type exactly", CLASSNAME, actualClassName);
+ }
+
+ protected String getActualClassName(Object object) {
+ String actualClassName = object.getClass().getName();
+ actualClassName = actualClassName.substring(actualClassName.lastIndexOf('.') + 1);
+ return actualClassName;
+ }
+
+ public void testByteAt() {
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+ stillEqual = (BYTES[i] == testString.byteAt(i));
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+ }
+
+ public void testByteIterator() {
+ boolean stillEqual = true;
+ ByteString.ByteIterator iter = testString.iterator();
+ for (int i = 0; stillEqual && i < BYTES.length; ++i) {
+ stillEqual = (iter.hasNext() && BYTES[i] == iter.nextByte());
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes", stillEqual);
+ assertFalse(CLASSNAME + " must have exhausted the itertor", iter.hasNext());
+
+ try {
+ iter.nextByte();
+ fail("Should have thrown an exception.");
+ } catch (NoSuchElementException e) {
+ // This is success
+ }
+ }
+
+ public void testByteIterable() {
+ boolean stillEqual = true;
+ int j = 0;
+ for (byte quantum : testString) {
+ stillEqual = (BYTES[j] == quantum);
+ ++j;
+ }
+ assertTrue(CLASSNAME + " must capture the right bytes as Bytes", stillEqual);
+ assertEquals(CLASSNAME + " iterable character count", BYTES.length, j);
+ }
+
+ public void testSize() {
+ assertEquals(CLASSNAME + " must have the expected size", BYTES.length,
+ testString.size());
+ }
+
+ public void testGetTreeDepth() {
+ assertEquals(CLASSNAME + " must have depth 0", 0, testString.getTreeDepth());
+ }
+
+ public void testIsBalanced() {
+ assertTrue(CLASSNAME + " is technically balanced", testString.isBalanced());
+ }
+
+ public void testCopyTo_ByteArrayOffsetLength() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+ int sourceOffset = 213;
+ testString.copyTo(destination, sourceOffset, destinationOffset, length);
+ boolean stillEqual = true;
+ for (int i = 0; stillEqual && i < length; ++i) {
+ stillEqual = BYTES[i + sourceOffset] == destination[i + destinationOffset];
+ }
+ assertTrue(CLASSNAME + ".copyTo(4 arg) must give the expected bytes", stillEqual);
+ }
+
+ public void testCopyTo_ByteArrayOffsetLengthErrors() {
+ int destinationOffset = 50;
+ int length = 100;
+ byte[] destination = new byte[destinationOffset + length];
+
+ try {
+ // Copy one too many bytes
+ testString.copyTo(destination, testString.size() + 1 - length,
+ destinationOffset, length);
+ fail("Should have thrown an exception when copying too many bytes of a "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative sourceOffset
+ testString.copyTo(destination, -1, destinationOffset, length);
+ fail("Should have thrown an exception when given a negative sourceOffset in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative destinationOffset
+ testString.copyTo(destination, 0, -1, length);
+ fail("Should have thrown an exception when given a negative destinationOffset in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal negative size
+ testString.copyTo(destination, 0, 0, -1);
+ fail("Should have thrown an exception when given a negative size in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large sourceOffset
+ testString.copyTo(destination, 2 * testString.size(), 0, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+
+ try {
+ // Copy with illegal too-large destinationOffset
+ testString.copyTo(destination, 0, 2 * destination.length, length);
+ fail("Should have thrown an exception when the destinationOffset is too large in "
+ + CLASSNAME);
+ } catch (IndexOutOfBoundsException expected) {
+ // This is success
+ }
+ }
+
+ public void testCopyTo_ByteBuffer() {
+ // Same length.
+ ByteBuffer myBuffer = ByteBuffer.allocate(BYTES.length);
+ testString.copyTo(myBuffer);
+ myBuffer.flip();
+ assertEquals(CLASSNAME + ".copyTo(ByteBuffer) must give back the same bytes",
+ backingBuffer, myBuffer);
+
+ // Target buffer bigger than required.
+ myBuffer = ByteBuffer.allocate(testString.size() + 1);
+ testString.copyTo(myBuffer);
+ myBuffer.flip();
+ assertEquals(backingBuffer, myBuffer);
+
+ // Target buffer has no space.
+ myBuffer = ByteBuffer.allocate(0);
+ try {
+ testString.copyTo(myBuffer);
+ fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+ } catch (BufferOverflowException e) {
+ // Expected.
+ }
+
+ // Target buffer too small.
+ myBuffer = ByteBuffer.allocate(1);
+ try {
+ testString.copyTo(myBuffer);
+ fail("Should have thrown an exception when target ByteBuffer has insufficient capacity");
+ } catch (BufferOverflowException e) {
+ // Expected.
+ }
+ }
+
+ public void testMarkSupported() {
+ InputStream stream = testString.newInput();
+ assertTrue(CLASSNAME + ".newInput() must support marking", stream.markSupported());
+ }
+
+ public void testMarkAndReset() throws IOException {
+ int fraction = testString.size() / 3;
+
+ InputStream stream = testString.newInput();
+ stream.mark(testString.size()); // First, mark() the end.
+
+ skipFully(stream, fraction); // Skip a large fraction, but not all.
+ assertEquals(
+ CLASSNAME + ": after skipping to the 'middle', half the bytes are available",
+ (testString.size() - fraction), stream.available());
+ stream.reset();
+ assertEquals(
+ CLASSNAME + ": after resetting, all bytes are available",
+ testString.size(), stream.available());
+
+ skipFully(stream, testString.size()); // Skip to the end.
+ assertEquals(
+ CLASSNAME + ": after skipping to the end, no more bytes are available",
+ 0, stream.available());
+ }
+
+ /**
+ * Discards {@code n} bytes of data from the input stream. This method
+ * will block until the full amount has been skipped. Does not close the
+ * stream.
+ * <p>Copied from com.google.common.io.ByteStreams to avoid adding dependency.
+ *
+ * @param in the input stream to read from
+ * @param n the number of bytes to skip
+ * @throws EOFException if this stream reaches the end before skipping all
+ * the bytes
+ * @throws IOException if an I/O error occurs, or the stream does not
+ * support skipping
+ */
+ static void skipFully(InputStream in, long n) throws IOException {
+ long toSkip = n;
+ while (n > 0) {
+ long amt = in.skip(n);
+ if (amt == 0) {
+ // Force a blocking read to avoid infinite loop
+ if (in.read() == -1) {
+ long skipped = toSkip - n;
+ throw new EOFException("reached end of stream after skipping "
+ + skipped + " bytes; " + toSkip + " bytes expected");
+ }
+ n--;
+ } else {
+ n -= amt;
+ }
+ }
+ }
+
+ public void testAsReadOnlyByteBuffer() {
+ ByteBuffer byteBuffer = testString.asReadOnlyByteBuffer();
+ byte[] roundTripBytes = new byte[BYTES.length];
+ assertTrue(byteBuffer.remaining() == BYTES.length);
+ assertTrue(byteBuffer.isReadOnly());
+ byteBuffer.get(roundTripBytes);
+ assertTrue(CLASSNAME + ".asReadOnlyByteBuffer() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testAsReadOnlyByteBufferList() {
+ List<ByteBuffer> byteBuffers = testString.asReadOnlyByteBufferList();
+ int bytesSeen = 0;
+ byte[] roundTripBytes = new byte[BYTES.length];
+ for (ByteBuffer byteBuffer : byteBuffers) {
+ int thisLength = byteBuffer.remaining();
+ assertTrue(byteBuffer.isReadOnly());
+ assertTrue(bytesSeen + thisLength <= BYTES.length);
+ byteBuffer.get(roundTripBytes, bytesSeen, thisLength);
+ bytesSeen += thisLength;
+ }
+ assertTrue(bytesSeen == BYTES.length);
+ assertTrue(CLASSNAME + ".asReadOnlyByteBufferTest() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testToByteArray() {
+ byte[] roundTripBytes = testString.toByteArray();
+ assertTrue(CLASSNAME + ".toByteArray() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testWriteTo() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ testString.writeTo(bos);
+ byte[] roundTripBytes = bos.toByteArray();
+ assertTrue(CLASSNAME + ".writeTo() must give back the same bytes",
+ Arrays.equals(BYTES, roundTripBytes));
+ }
+
+ public void testWriteToShouldNotExposeInternalBufferToOutputStream() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ Arrays.fill(b, off, off + len, (byte) 0);
+ }
+
+ @Override
+ public void write(int b) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ byte[] original = Arrays.copyOf(BYTES, BYTES.length);
+ testString.writeTo(os);
+ assertTrue(CLASSNAME + ".writeTo() must NOT grant access to underlying buffer",
+ Arrays.equals(original, BYTES));
+ }
+
+ public void testWriteToInternalShouldExposeInternalBufferToOutputStream() throws IOException {
+ OutputStream os = new OutputStream() {
+ @Override
+ public void write(byte[] b, int off, int len) {
+ Arrays.fill(b, off, off + len, (byte) 0);
+ }
+
+ @Override
+ public void write(int b) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
+ testString.writeToInternal(os, 0, testString.size());
+ byte[] allZeros = new byte[testString.size()];
+ assertTrue(CLASSNAME + ".writeToInternal() must grant access to underlying buffer",
+ Arrays.equals(allZeros, backingBuffer.array()));
+ }
+
+ public void testWriteToShouldExposeInternalBufferToByteOutput() throws IOException {
+ ByteOutput out = new ByteOutput() {
+ @Override
+ public void write(byte value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ Arrays.fill(value.array(), value.arrayOffset(), value.arrayOffset() + value.limit(),
+ (byte) 0);
+ }
+ };
+
+ testString.writeTo(out);
+ byte[] allZeros = new byte[testString.size()];
+ assertTrue(CLASSNAME + ".writeTo() must grant access to underlying buffer",
+ Arrays.equals(allZeros, backingBuffer.array()));
+ }
+
+ public void testNewOutput() throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ByteString.Output output = ByteString.newOutput();
+ testString.writeTo(output);
+ assertEquals("Output Size returns correct result",
+ output.size(), testString.size());
+ output.writeTo(bos);
+ assertTrue("Output.writeTo() must give back the same bytes",
+ Arrays.equals(BYTES, bos.toByteArray()));
+
+ // write the output stream to itself! This should cause it to double
+ output.writeTo(output);
+ assertEquals("Writing an output stream to itself is successful",
+ testString.concat(testString), output.toByteString());
+
+ output.reset();
+ assertEquals("Output.reset() resets the output", 0, output.size());
+ assertEquals("Output.reset() resets the output",
+ EMPTY, output.toByteString());
+ }
+
+ public void testToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = forString(testString);
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+ }
+
+ public void testCharsetToString() {
+ String testString = "I love unicode \u1234\u5678 characters";
+ ByteString unicode = forString(testString);
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(CLASSNAME + " unicode must match", testString, roundTripString);
+ }
+
+ public void testToString_returnsCanonicalEmptyString() {
+ assertSame(CLASSNAME + " must be the same string references",
+ EMPTY.toString(UTF_8),
+ new NioByteString(ByteBuffer.wrap(new byte[0])).toString(UTF_8));
+ }
+
+ public void testToString_raisesException() {
+ try {
+ EMPTY.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ testString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ public void testEquals() {
+ assertEquals(CLASSNAME + " must not equal null", false, testString.equals(null));
+ assertEquals(CLASSNAME + " must equal self", testString, testString);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ testString.equals(EMPTY));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ EMPTY, testString.substring(55, 55));
+ assertEquals(CLASSNAME + " must equal another string with the same value",
+ testString, new NioByteString(backingBuffer));
+
+ byte[] mungedBytes = mungedBytes();
+ assertFalse(CLASSNAME + " must not equal every string with the same length",
+ testString.equals(new NioByteString(ByteBuffer.wrap(mungedBytes))));
+ }
+
+ public void testEqualsLiteralByteString() {
+ ByteString literal = ByteString.copyFrom(BYTES);
+ assertEquals(CLASSNAME + " must equal LiteralByteString with same value", literal,
+ testString);
+ assertEquals(CLASSNAME + " must equal LiteralByteString with same value", testString,
+ literal);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ testString.equals(ByteString.EMPTY));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ ByteString.EMPTY, testString.substring(55, 55));
+
+ literal = ByteString.copyFrom(mungedBytes());
+ assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+ testString.equals(literal));
+ assertFalse(CLASSNAME + " must not equal every LiteralByteString with the same length",
+ literal.equals(testString));
+ }
+
+ public void testEqualsRopeByteString() {
+ ByteString p1 = ByteString.copyFrom(BYTES, 0, 5);
+ ByteString p2 = ByteString.copyFrom(BYTES, 5, BYTES.length - 5);
+ ByteString rope = p1.concat(p2);
+
+ assertEquals(CLASSNAME + " must equal RopeByteString with same value", rope,
+ testString);
+ assertEquals(CLASSNAME + " must equal RopeByteString with same value", testString,
+ rope);
+ assertFalse(CLASSNAME + " must not equal the empty string",
+ testString.equals(ByteString.EMPTY.concat(ByteString.EMPTY)));
+ assertEquals(CLASSNAME + " empty strings must be equal",
+ ByteString.EMPTY.concat(ByteString.EMPTY), testString.substring(55, 55));
+
+ byte[] mungedBytes = mungedBytes();
+ p1 = ByteString.copyFrom(mungedBytes, 0, 5);
+ p2 = ByteString.copyFrom(mungedBytes, 5, mungedBytes.length - 5);
+ rope = p1.concat(p2);
+ assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+ testString.equals(rope));
+ assertFalse(CLASSNAME + " must not equal every RopeByteString with the same length",
+ rope.equals(testString));
+ }
+
+ private byte[] mungedBytes() {
+ byte[] mungedBytes = new byte[BYTES.length];
+ System.arraycopy(BYTES, 0, mungedBytes, 0, BYTES.length);
+ mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF);
+ return mungedBytes;
+ }
+
+ public void testHashCode() {
+ int hash = testString.hashCode();
+ assertEquals(CLASSNAME + " must have expected hashCode", EXPECTED_HASH, hash);
+ }
+
+ public void testPeekCachedHashCode() {
+ ByteString newString = new NioByteString(backingBuffer);
+ assertEquals(CLASSNAME + ".peekCachedHashCode() should return zero at first", 0,
+ newString.peekCachedHashCode());
+ newString.hashCode();
+ assertEquals(CLASSNAME + ".peekCachedHashCode should return zero at first",
+ EXPECTED_HASH, newString.peekCachedHashCode());
+ }
+
+ public void testPartialHash() {
+ // partialHash() is more strenuously tested elsewhere by testing hashes of substrings.
+ // This test would fail if the expected hash were 1. It's not.
+ int hash = testString.partialHash(testString.size(), 0, testString.size());
+ assertEquals(CLASSNAME + ".partialHash() must yield expected hashCode",
+ EXPECTED_HASH, hash);
+ }
+
+ public void testNewInput() throws IOException {
+ InputStream input = testString.newInput();
+ assertEquals("InputStream.available() returns correct value",
+ testString.size(), input.available());
+ boolean stillEqual = true;
+ for (byte referenceByte : BYTES) {
+ int expectedInt = (referenceByte & 0xFF);
+ stillEqual = (expectedInt == input.read());
+ }
+ assertEquals("InputStream.available() returns correct value",
+ 0, input.available());
+ assertTrue(CLASSNAME + " must give the same bytes from the InputStream", stillEqual);
+ assertEquals(CLASSNAME + " InputStream must now be exhausted", -1, input.read());
+ }
+
+ public void testNewInput_skip() throws IOException {
+ InputStream input = testString.newInput();
+ int stringSize = testString.size();
+ int nearEndIndex = stringSize * 2 / 3;
+ long skipped1 = input.skip(nearEndIndex);
+ assertEquals("InputStream.skip()", skipped1, nearEndIndex);
+ assertEquals("InputStream.available()",
+ stringSize - skipped1, input.available());
+ assertTrue("InputStream.mark() is available", input.markSupported());
+ input.mark(0);
+ assertEquals("InputStream.skip(), read()",
+ testString.byteAt(nearEndIndex) & 0xFF, input.read());
+ assertEquals("InputStream.available()",
+ stringSize - skipped1 - 1, input.available());
+ long skipped2 = input.skip(stringSize);
+ assertEquals("InputStream.skip() incomplete",
+ skipped2, stringSize - skipped1 - 1);
+ assertEquals("InputStream.skip(), no more input", 0, input.available());
+ assertEquals("InputStream.skip(), no more input", -1, input.read());
+ input.reset();
+ assertEquals("InputStream.reset() succeded",
+ stringSize - skipped1, input.available());
+ assertEquals("InputStream.reset(), read()",
+ testString.byteAt(nearEndIndex) & 0xFF, input.read());
+ }
+
+ public void testNewCodedInput() throws IOException {
+ CodedInputStream cis = testString.newCodedInput();
+ byte[] roundTripBytes = cis.readRawBytes(BYTES.length);
+ assertTrue(CLASSNAME + " must give the same bytes back from the CodedInputStream",
+ Arrays.equals(BYTES, roundTripBytes));
+ assertTrue(CLASSNAME + " CodedInputStream must now be exhausted", cis.isAtEnd());
+ }
+
+ /**
+ * Make sure we keep things simple when concatenating with empty. See also
+ * {@link ByteStringTest#testConcat_empty()}.
+ */
+ public void testConcat_empty() {
+ assertSame(CLASSNAME + " concatenated with empty must give " + CLASSNAME,
+ testString.concat(EMPTY), testString);
+ assertSame("empty concatenated with " + CLASSNAME + " must give " + CLASSNAME,
+ EMPTY.concat(testString), testString);
+ }
+
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(testString);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", testString, o);
+ }
+
+ private static ByteString forString(String str) {
+ return new NioByteString(ByteBuffer.wrap(str.getBytes(UTF_8)));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
new file mode 100644
index 0000000000..e376b1cd72
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java
@@ -0,0 +1,271 @@
+// 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+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 org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * 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)
+ */
+@RunWith(JUnit4.class)
+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() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(in);
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_InputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(in, ExtensionRegistry.newInstance());
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_CodedInputStream() {
+ setup();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseFrom(CodedInputStream.newInstance(in));
+ }
+ });
+ }
+
+ @Test public void message_parseFrom_CodedInputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ 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() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseDelimitedFrom(in);
+ }
+ });
+ }
+
+ @Test public void message_parseDelimitedFrom_InputStreamAndExtensionRegistry() {
+ setupDelimited();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.parseDelimitedFrom(in, ExtensionRegistry.newInstance());
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_InputStream() {
+ setup();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ public DescriptorProto parse(InputStream in) throws IOException {
+ return DescriptorProto.newBuilder().mergeFrom(in).build();
+ }
+ });
+ }
+
+ @Test public void messageBuilder_mergeFrom_InputStreamAndExtensionRegistry() {
+ setup();
+ verifyExceptions(
+ new ParseTester() {
+ @Override
+ 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() {
+ @Override
+ 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() {
+ @Override
+ 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() {
+ @Override
+ 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() {
+ @Override
+ 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/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParserTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParserTest.java
new file mode 100644
index 0000000000..8c2e4c261c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ParserTest.java
@@ -0,0 +1,415 @@
+// 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 com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.UnittestLite.TestParsingMergeLite;
+import protobuf_unittest.UnittestOptimizeFor;
+import protobuf_unittest.UnittestOptimizeFor.TestOptimizedForSize;
+import protobuf_unittest.UnittestOptimizeFor.TestRequiredOptimizedForSize;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestParsingMerge;
+import protobuf_unittest.UnittestProto.TestRequired;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import junit.framework.TestCase;
+
+/**
+ * Unit test for {@link Parser}.
+ *
+ * @author liujisi@google.com (Pherl Liu)
+ */
+public class ParserTest extends TestCase {
+ public void testGeneratedMessageParserSingleton() throws Exception {
+ for (int i = 0; i < 10; i++) {
+ assertEquals(TestAllTypes.parser(), TestUtil.getAllSet().getParserForType());
+ }
+ }
+
+ private void assertRoundTripEquals(MessageLite message,
+ ExtensionRegistryLite registry)
+ throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+ Parser<? extends MessageLite> parser = message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length, registry));
+ assertMessageEquals(message, parser.parseFrom(
+ message.toByteString(), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data), registry));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data), registry));
+ }
+
+ @SuppressWarnings("unchecked")
+ private void assertRoundTripEquals(MessageLite message) throws Exception {
+ final byte[] data = message.toByteArray();
+ final int offset = 20;
+ final int length = data.length;
+ final int padding = 30;
+
+ Parser<MessageLite> parser =
+ (Parser<MessageLite>) message.getParserForType();
+ assertMessageEquals(message, parser.parseFrom(data));
+ assertMessageEquals(message, parser.parseFrom(
+ generatePaddingArray(data, offset, padding),
+ offset, length));
+ assertMessageEquals(message, parser.parseFrom(message.toByteString()));
+ assertMessageEquals(message, parser.parseFrom(
+ new ByteArrayInputStream(data)));
+ assertMessageEquals(message, parser.parseFrom(
+ CodedInputStream.newInstance(data)));
+ }
+
+ private void assertMessageEquals(
+ MessageLite expected, MessageLite actual)
+ throws Exception {
+ if (expected instanceof Message) {
+ assertEquals(expected, actual);
+ } else {
+ assertEquals(expected.toByteString(), actual.toByteString());
+ }
+ }
+
+ private byte[] generatePaddingArray(byte[] data, int offset, int padding) {
+ byte[] result = new byte[offset + data.length + padding];
+ System.arraycopy(data, 0, result, offset, data.length);
+ return result;
+ }
+
+ public void testNormalMessage() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllSet());
+ }
+
+
+ public void testParsePartial() throws Exception {
+ assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
+ }
+
+ private <T extends MessageLite> void assertParsePartial(
+ Parser<T> parser, T partialMessage) throws Exception {
+ final String errorString =
+ "Should throw exceptions when the parsed message isn't initialized.";
+
+ // parsePartialFrom should pass.
+ byte[] data = partialMessage.toByteArray();
+ assertEquals(partialMessage, parser.parsePartialFrom(data));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ partialMessage.toByteString()));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ new ByteArrayInputStream(data)));
+ assertEquals(partialMessage, parser.parsePartialFrom(
+ CodedInputStream.newInstance(data)));
+
+ // parseFrom(ByteArray)
+ try {
+ parser.parseFrom(partialMessage.toByteArray());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(ByteString)
+ try {
+ parser.parseFrom(partialMessage.toByteString());
+ fail(errorString);
+ } catch (InvalidProtocolBufferException e) {
+ // pass.
+ }
+
+ // parseFrom(InputStream)
+ try {
+ parser.parseFrom(new ByteArrayInputStream(partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+
+ // parseFrom(CodedInputStream)
+ try {
+ parser.parseFrom(CodedInputStream.newInstance(
+ partialMessage.toByteArray()));
+ fail(errorString);
+ } catch (IOException e) {
+ // pass.
+ }
+ }
+
+ public void testParseExtensions() throws Exception {
+ assertRoundTripEquals(TestUtil.getAllExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(
+ TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+ }
+
+ public void testParsePacked() throws Exception {
+ assertRoundTripEquals(TestUtil.getPackedSet());
+ assertRoundTripEquals(TestUtil.getPackedExtensionsSet(),
+ TestUtil.getExtensionRegistry());
+ assertRoundTripEquals(
+ TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+ }
+
+ public void testParseDelimitedTo() throws Exception {
+ // Write normal Message.
+ TestAllTypes normalMessage = TestUtil.getAllSet();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ normalMessage.writeDelimitedTo(output);
+
+ // Write MessageLite with packed extension fields.
+ TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet();
+ packedMessage.writeDelimitedTo(output);
+
+ InputStream input = new ByteArrayInputStream(output.toByteArray());
+ assertMessageEquals(
+ normalMessage,
+ normalMessage.getParserForType().parseDelimitedFrom(input));
+ assertMessageEquals(
+ packedMessage,
+ packedMessage
+ .getParserForType()
+ .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
+ }
+
+ public void testParseUnknownFields() throws Exception {
+ // All fields will be treated as unknown fields in emptyMessage.
+ TestEmptyMessage emptyMessage =
+ TestEmptyMessage.parser().parseFrom(TestUtil.getAllSet().toByteString());
+ assertEquals(
+ TestUtil.getAllSet().toByteString(),
+ emptyMessage.toByteString());
+ }
+
+
+ public void testOptimizeForSize() throws Exception {
+ TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
+ builder.setI(12).setMsg(ForeignMessage.newBuilder().setC(34).build());
+ builder.setExtension(TestOptimizedForSize.testExtension, 56);
+ builder.setExtension(TestOptimizedForSize.testExtension2,
+ TestRequiredOptimizedForSize.newBuilder().setX(78).build());
+
+ TestOptimizedForSize message = builder.build();
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestOptimizeFor.registerAllExtensions(registry);
+
+ assertRoundTripEquals(message, registry);
+ }
+
+ /** Helper method for {@link #testParsingMerge()}.*/
+ private void assertMessageMerged(TestAllTypes allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ /** Helper method for {@link #testParsingMergeLite()}.*/
+ private void assertMessageMerged(TestAllTypesLite allTypes)
+ throws Exception {
+ assertEquals(3, allTypes.getOptionalInt32());
+ assertEquals(2, allTypes.getOptionalInt64());
+ assertEquals("hello", allTypes.getOptionalString());
+ }
+
+ public void testParsingMerge() throws Exception {
+ // Build messages.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TestAllTypes msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypes msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypes msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMerge.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMerge.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMerge.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMerge.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestProto.registerAllExtensions(registry);
+ TestParsingMerge parsingMerge = TestParsingMerge.parser().parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMerge.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMerge.repeatedExt));
+ }
+
+ public void testParsingMergeLite() throws Exception {
+ // Build messages.
+ TestAllTypesLite.Builder builder =
+ TestAllTypesLite.newBuilder();
+ TestAllTypesLite msg1 = builder.setOptionalInt32(1).build();
+ builder.clear();
+ TestAllTypesLite msg2 = builder.setOptionalInt64(2).build();
+ builder.clear();
+ TestAllTypesLite msg3 = builder.setOptionalInt32(3)
+ .setOptionalString("hello").build();
+
+ // Build groups.
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1 optionalG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group1.newBuilder()
+ .setField1(msg3).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG1 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg1).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG2 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg2).build();
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2 repeatedG3 =
+ TestParsingMergeLite.RepeatedFieldsGenerator.Group2.newBuilder()
+ .setField1(msg3).build();
+
+ // Assign and serialize RepeatedFieldsGenerator.
+ ByteString data = TestParsingMergeLite.RepeatedFieldsGenerator.newBuilder()
+ .addField1(msg1).addField1(msg2).addField1(msg3)
+ .addField2(msg1).addField2(msg2).addField2(msg3)
+ .addField3(msg1).addField3(msg2).addField3(msg3)
+ .addGroup1(optionalG1).addGroup1(optionalG2).addGroup1(optionalG3)
+ .addGroup2(repeatedG1).addGroup2(repeatedG2).addGroup2(repeatedG3)
+ .addExt1(msg1).addExt1(msg2).addExt1(msg3)
+ .addExt2(msg1).addExt2(msg2).addExt2(msg3)
+ .build().toByteString();
+
+ // Parse TestParsingMergeLite.
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestLite.registerAllExtensions(registry);
+ TestParsingMergeLite parsingMerge = TestParsingMergeLite.parser().parseFrom(data, registry);
+
+ // Required and optional fields should be merged.
+ assertMessageMerged(parsingMerge.getRequiredAllTypes());
+ assertMessageMerged(parsingMerge.getOptionalAllTypes());
+ assertMessageMerged(
+ parsingMerge.getOptionalGroup().getOptionalGroupAllTypes());
+ assertMessageMerged(parsingMerge.getExtension(
+ TestParsingMergeLite.optionalExt));
+
+ // Repeated fields should not be merged.
+ assertEquals(3, parsingMerge.getRepeatedAllTypesCount());
+ assertEquals(3, parsingMerge.getRepeatedGroupCount());
+ assertEquals(3, parsingMerge.getExtensionCount(
+ TestParsingMergeLite.repeatedExt));
+ }
+
+ public void testParseDelimitedFrom_firstByteInterrupted_preservesCause() {
+ try {
+ TestUtil.getAllSet().parseDelimitedFrom(
+ new InputStream() {
+ @Override
+ public int read() throws IOException {
+ throw new InterruptedIOException();
+ }
+ });
+ fail("Expected InterruptedIOException");
+ } catch (Exception e) {
+ assertEquals(InterruptedIOException.class, e.getClass());
+ }
+ }
+
+ public void testParseDelimitedFrom_secondByteInterrupted_preservesCause() {
+ try {
+ TestUtil.getAllSet().parseDelimitedFrom(
+ new InputStream() {
+ private int i;
+
+ @Override
+ public int read() throws IOException {
+ switch (i++) {
+ case 0:
+ return 1;
+ case 1:
+ throw new InterruptedIOException();
+ default:
+ throw new AssertionError();
+ }
+ }
+ });
+ fail("Expected InterruptedIOException");
+ } catch (Exception e) {
+ assertEquals(InterruptedIOException.class, e.getClass());
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
new file mode 100644
index 0000000000..af717bfd20
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java
@@ -0,0 +1,288 @@
+// 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 static java.util.Arrays.asList;
+
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link ProtobufArrayList}.
+ */
+public class ProtobufArrayListTest extends TestCase {
+
+ private static final ProtobufArrayList<Integer> UNARY_LIST = newImmutableProtoArrayList(1);
+ private static final ProtobufArrayList<Integer> TERTIARY_LIST =
+ newImmutableProtoArrayList(1, 2, 3);
+
+ private ProtobufArrayList<Integer> list;
+
+ @Override
+ protected void setUp() throws Exception {
+ list = new ProtobufArrayList<Integer>();
+ }
+
+ public void testEmptyListReturnsSameInstance() {
+ assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList());
+ }
+
+ public void testEmptyListIsImmutable() {
+ assertImmutable(ProtobufArrayList.<Integer>emptyList());
+ }
+
+ public void testModificationWithIteration() {
+ list.addAll(asList(1, 2, 3, 4));
+ Iterator<Integer> iterator = list.iterator();
+ assertEquals(4, list.size());
+ assertEquals(1, (int) list.get(0));
+ assertEquals(1, (int) iterator.next());
+
+ list.remove(0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.set(0, 1);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+
+ iterator = list.iterator();
+ list.add(0, 0);
+ try {
+ iterator.next();
+ fail();
+ } catch (ConcurrentModificationException e) {
+ // expected
+ }
+ }
+
+ public void testMakeImmutable() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+ list.add(8);
+ list.makeImmutable();
+ assertImmutable(list);
+ }
+
+ public void testRemove() {
+ list.add(2);
+ list.add(4);
+ list.add(6);
+
+ list.remove(1);
+ assertEquals(asList(2, 6), list);
+
+ list.remove(1);
+ assertEquals(asList(2), list);
+
+ list.remove(0);
+ assertEquals(asList(), list);
+ }
+
+ public void testGet() {
+ list.add(2);
+ list.add(6);
+
+ assertEquals(2, (int) list.get(0));
+ assertEquals(6, (int) list.get(1));
+ }
+
+ public void testSet() {
+ list.add(2);
+ list.add(6);
+
+ list.set(0, 1);
+ assertEquals(1, (int) list.get(0));
+ list.set(1, 2);
+ assertEquals(2, (int) list.get(1));
+ }
+
+ private void assertImmutable(List<Integer> list) {
+ if (list.contains(1)) {
+ throw new RuntimeException("Cannot test the immutability of lists that contain 1.");
+ }
+
+ try {
+ list.add(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.add(0, 1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(Collections.singletonList(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(new ProtobufArrayList<Integer>());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.addAll(0, Collections.<Integer>emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.clear();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(1);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.remove(new Object());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.removeAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.emptyList());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(Collections.singleton(1));
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.retainAll(UNARY_LIST);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ list.set(0, 0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private static ProtobufArrayList<Integer> newImmutableProtoArrayList(int... elements) {
+ ProtobufArrayList<Integer> list = new ProtobufArrayList<Integer>();
+ for (int element : elements) {
+ list.add(element);
+ }
+ list.makeImmutable();
+ return list;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java
new file mode 100644
index 0000000000..edbd0afd75
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java
@@ -0,0 +1,188 @@
+// 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 protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import java.util.Collections;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link RepeatedFieldBuilderV3}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class RepeatedFieldBuilderV3Test extends TestCase {
+
+ public void testBasicUse() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ List<TestAllTypes> list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+
+ // Make sure it doesn't change.
+ List<TestAllTypes> list2 = builder.build();
+ assertSame(list, list2);
+ assertEquals(0, mockParent.getInvalidationCount());
+ }
+
+ public void testGoingBackAndForth() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ // Convert to list
+ List<TestAllTypes> list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+
+ // Update 0th item
+ assertEquals(0, mockParent.getInvalidationCount());
+ builder.getBuilder(0).setOptionalString("foo");
+ assertEquals(1, mockParent.getInvalidationCount());
+ list = builder.build();
+ assertEquals(2, list.size());
+ assertEquals(0, list.get(0).getOptionalInt32());
+ assertEquals("foo", list.get(0).getOptionalString());
+ assertEquals(1, list.get(1).getOptionalInt32());
+ assertIsUnmodifiable(list);
+ assertEquals(1, mockParent.getInvalidationCount());
+ }
+
+ public void testVariousMethods() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(2).build());
+ builder.addBuilder(0, TestAllTypes.getDefaultInstance())
+ .setOptionalInt32(0);
+ builder.addBuilder(TestAllTypes.getDefaultInstance()).setOptionalInt32(3);
+
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+ assertEquals(2, builder.getMessage(2).getOptionalInt32());
+ assertEquals(3, builder.getMessage(3).getOptionalInt32());
+
+ assertEquals(0, mockParent.getInvalidationCount());
+ List<TestAllTypes> messages = builder.build();
+ assertEquals(4, messages.size());
+ assertSame(messages, builder.build()); // expect same list
+
+ // Remove a message.
+ builder.remove(2);
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(3, builder.getCount());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+ assertEquals(3, builder.getMessage(2).getOptionalInt32());
+
+ // Remove a builder.
+ builder.remove(0);
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(2, builder.getCount());
+ assertEquals(1, builder.getMessage(0).getOptionalInt32());
+ assertEquals(3, builder.getMessage(1).getOptionalInt32());
+
+ // Test clear.
+ builder.clear();
+ assertEquals(1, mockParent.getInvalidationCount());
+ assertEquals(0, builder.getCount());
+ assertTrue(builder.isEmpty());
+ }
+
+ public void testLists() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder = newRepeatedFieldBuilderV3(mockParent);
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(1).build());
+ builder.addMessage(0,
+ TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertEquals(0, builder.getMessage(0).getOptionalInt32());
+ assertEquals(1, builder.getMessage(1).getOptionalInt32());
+
+ // Use list of builders.
+ List<TestAllTypes.Builder> builders = builder.getBuilderList();
+ assertEquals(0, builders.get(0).getOptionalInt32());
+ assertEquals(1, builders.get(1).getOptionalInt32());
+ builders.get(0).setOptionalInt32(10);
+ builders.get(1).setOptionalInt32(11);
+
+ // Use list of protos
+ List<TestAllTypes> protos = builder.getMessageList();
+ assertEquals(10, protos.get(0).getOptionalInt32());
+ assertEquals(11, protos.get(1).getOptionalInt32());
+
+ // Add an item to the builders and verify it's updated in both
+ builder.addMessage(TestAllTypes.newBuilder().setOptionalInt32(12).build());
+ assertEquals(3, builders.size());
+ assertEquals(3, protos.size());
+ }
+
+ private void assertIsUnmodifiable(List<?> list) {
+ if (list == Collections.emptyList()) {
+ // OKAY -- Need to check this b/c EmptyList allows you to call clear.
+ } else {
+ try {
+ list.clear();
+ fail("List wasn't immutable");
+ } catch (UnsupportedOperationException e) {
+ // good
+ }
+ }
+ }
+
+ private RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>
+ newRepeatedFieldBuilderV3(GeneratedMessage.BuilderParent parent) {
+ return new RepeatedFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(Collections.<TestAllTypes>emptyList(), false,
+ parent, false);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
new file mode 100644
index 0000000000..dc56f2e9ac
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java
@@ -0,0 +1,127 @@
+// 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.UnsupportedEncodingException;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString#substring(int, int)} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringSubstringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ byte[] sourceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(sourceBytes).iterator();
+ ByteString sourceString = iter.next();
+ while (iter.hasNext()) {
+ sourceString = sourceString.concat(iter.next());
+ }
+
+ int from = 1130;
+ int to = sourceBytes.length - 5555;
+ stringUnderTest = sourceString.substring(from, to);
+ referenceBytes = new byte[to - from];
+ System.arraycopy(sourceBytes, from, referenceBytes, 0, to - from);
+ expectedHashCode = -1259260680;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 3, stringUnderTest.getTreeDepth());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ // Do the substring part
+ testString = testString.substring(2, testString.length() - 6);
+ unicode = unicode.substring(2, unicode.size() - 6);
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ // Do the substring part
+ testString = testString.substring(2, testString.length() - 6);
+ unicode = unicode.substring(2, unicode.size() - 6);
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
new file mode 100644
index 0000000000..4ec3a40988
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java
@@ -0,0 +1,189 @@
+// 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.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/**
+ * This class tests {@link RopeByteString} by inheriting the tests from
+ * {@link LiteralByteStringTest}. Only a couple of methods are overridden.
+ *
+ * <p>A full test of the result of {@link RopeByteString#substring(int, int)} is found in the
+ * separate class {@link RopeByteStringSubstringTest}.
+ *
+ * @author carlanton@google.com (Carl Haverl)
+ */
+public class RopeByteStringTest extends LiteralByteStringTest {
+
+ @Override
+ protected void setUp() throws Exception {
+ classUnderTest = "RopeByteString";
+ referenceBytes = ByteStringTest.getTestBytes(22341, 22337766L);
+ Iterator<ByteString> iter = ByteStringTest.makeConcretePieces(referenceBytes).iterator();
+ stringUnderTest = iter.next();
+ while (iter.hasNext()) {
+ stringUnderTest = stringUnderTest.concat(iter.next());
+ }
+ expectedHashCode = -1214197238;
+ }
+
+ @Override
+ public void testGetTreeDepth() {
+ assertEquals(classUnderTest + " must have the expected tree depth",
+ 4, stringUnderTest.getTreeDepth());
+ }
+
+ public void testBalance() {
+ int numberOfPieces = 10000;
+ int pieceSize = 64;
+ byte[] testBytes = ByteStringTest.getTestBytes(numberOfPieces * pieceSize, 113377L);
+
+ // Build up a big ByteString from smaller pieces to force a rebalance
+ ByteString concatenated = ByteString.EMPTY;
+ for (int i = 0; i < numberOfPieces; ++i) {
+ concatenated = concatenated.concat(ByteString.copyFrom(testBytes, i * pieceSize, pieceSize));
+ }
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(concatenated));
+ assertTrue(classUnderTest + " underlying bytes must match after balancing",
+ Arrays.equals(testBytes, concatenated.toByteArray()));
+ ByteString testString = ByteString.copyFrom(testBytes);
+ assertTrue(classUnderTest + " balanced string must equal flat string",
+ concatenated.equals(testString));
+ assertTrue(classUnderTest + " flat string must equal balanced string",
+ testString.equals(concatenated));
+ assertEquals(classUnderTest + " balanced string must have same hash code as flat string",
+ testString.hashCode(), concatenated.hashCode());
+ }
+
+ @Override
+ public void testToString() throws UnsupportedEncodingException {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testCharsetToString() {
+ String sourceString = "I love unicode \u1234\u5678 characters";
+ ByteString sourceByteString = ByteString.copyFromUtf8(sourceString);
+ int copies = 250;
+
+ // By building the RopeByteString by concatenating, this is actually a fairly strenuous test.
+ StringBuilder builder = new StringBuilder(copies * sourceString.length());
+ ByteString unicode = ByteString.EMPTY;
+ for (int i = 0; i < copies; ++i) {
+ builder.append(sourceString);
+ unicode = RopeByteString.concatenate(unicode, sourceByteString);
+ }
+ String testString = builder.toString();
+
+ assertEquals(classUnderTest + " from string must have the expected type",
+ classUnderTest, getActualClassName(unicode));
+ String roundTripString = unicode.toString(Internal.UTF_8);
+ assertEquals(classUnderTest + " unicode bytes must match",
+ testString, roundTripString);
+ ByteString flatString = ByteString.copyFromUtf8(testString);
+ assertEquals(classUnderTest + " string must equal the flat string", flatString, unicode);
+ assertEquals(classUnderTest + " string must must have same hashCode as the flat string",
+ flatString.hashCode(), unicode.hashCode());
+ }
+
+ @Override
+ public void testToString_returnsCanonicalEmptyString() {
+ RopeByteString ropeByteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ assertSame(classUnderTest + " must be the same string references",
+ ByteString.EMPTY.toString(Internal.UTF_8), ropeByteString.toString(Internal.UTF_8));
+ }
+
+ @Override
+ public void testToString_raisesException() {
+ try {
+ ByteString byteString =
+ RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY);
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+
+ try {
+ ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"),
+ ByteString.copyFromUtf8("bar"));
+ byteString.toString("invalid");
+ fail("Should have thrown an exception.");
+ } catch (UnsupportedEncodingException expected) {
+ // This is success
+ }
+ }
+
+ @Override
+ public void testJavaSerialization() throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(out);
+ oos.writeObject(stringUnderTest);
+ oos.close();
+ byte[] pickled = out.toByteArray();
+ InputStream in = new ByteArrayInputStream(pickled);
+ ObjectInputStream ois = new ObjectInputStream(in);
+ Object o = ois.readObject();
+ assertTrue("Didn't get a ByteString back", o instanceof ByteString);
+ assertEquals("Should get an equal ByteString back", stringUnderTest, o);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ServiceTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ServiceTest.java
new file mode 100644
index 0000000000..b895ad8d36
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/ServiceTest.java
@@ -0,0 +1,326 @@
+// 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 com.google.protobuf.Descriptors.FileDescriptor;
+import com.google.protobuf.Descriptors.MethodDescriptor;
+import google.protobuf.no_generic_services_test.UnittestNoGenericServices;
+import protobuf_unittest.MessageWithNoOuter;
+import protobuf_unittest.ServiceWithNoOuter;
+import protobuf_unittest.UnittestProto.BarRequest;
+import protobuf_unittest.UnittestProto.BarResponse;
+import protobuf_unittest.UnittestProto.FooRequest;
+import protobuf_unittest.UnittestProto.FooResponse;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestService;
+
+import java.util.HashSet;
+import java.util.Set;
+import junit.framework.TestCase;
+import org.easymock.classextension.EasyMock;
+import org.easymock.IArgumentMatcher;
+import org.easymock.classextension.IMocksControl;
+
+/**
+ * Tests services and stubs.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public class ServiceTest extends TestCase {
+ private IMocksControl control;
+ private RpcController mockController;
+
+ private final Descriptors.MethodDescriptor fooDescriptor =
+ TestService.getDescriptor().getMethods().get(0);
+ private final Descriptors.MethodDescriptor barDescriptor =
+ TestService.getDescriptor().getMethods().get(1);
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ control = EasyMock.createStrictControl();
+ mockController = control.createMock(RpcController.class);
+ }
+
+ // =================================================================
+
+ /** Tests Service.callMethod(). */
+ public void testCallMethod() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<Message> fooCallback = new MockCallback<Message>();
+ MockCallback<Message> barCallback = new MockCallback<Message>();
+ TestService mockService = control.createMock(TestService.class);
+
+ mockService.foo(EasyMock.same(mockController), EasyMock.same(fooRequest),
+ this.<FooResponse>wrapsCallback(fooCallback));
+ mockService.bar(EasyMock.same(mockController), EasyMock.same(barRequest),
+ this.<BarResponse>wrapsCallback(barCallback));
+ control.replay();
+
+ mockService.callMethod(fooDescriptor, mockController,
+ fooRequest, fooCallback);
+ mockService.callMethod(barDescriptor, mockController,
+ barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests Service.get{Request,Response}Prototype(). */
+ public void testGetPrototype() throws Exception {
+ TestService mockService = control.createMock(TestService.class);
+
+ assertSame(mockService.getRequestPrototype(fooDescriptor),
+ FooRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(fooDescriptor),
+ FooResponse.getDefaultInstance());
+ assertSame(mockService.getRequestPrototype(barDescriptor),
+ BarRequest.getDefaultInstance());
+ assertSame(mockService.getResponsePrototype(barDescriptor),
+ BarResponse.getDefaultInstance());
+ }
+
+ /** Tests generated stubs. */
+ public void testStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ MockCallback<FooResponse> fooCallback = new MockCallback<FooResponse>();
+ MockCallback<BarResponse> barCallback = new MockCallback<BarResponse>();
+ RpcChannel mockChannel = control.createMock(RpcChannel.class);
+ TestService stub = TestService.newStub(mockChannel);
+
+ mockChannel.callMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(fooCallback));
+ mockChannel.callMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()),
+ this.<Message>wrapsCallback(barCallback));
+ control.replay();
+
+ stub.foo(mockController, fooRequest, fooCallback);
+ stub.bar(mockController, barRequest, barCallback);
+ control.verify();
+ }
+
+ /** Tests generated blocking stubs. */
+ public void testBlockingStub() throws Exception {
+ FooRequest fooRequest = FooRequest.newBuilder().build();
+ BarRequest barRequest = BarRequest.newBuilder().build();
+ BlockingRpcChannel mockChannel =
+ control.createMock(BlockingRpcChannel.class);
+ TestService.BlockingInterface stub =
+ TestService.newBlockingStub(mockChannel);
+
+ FooResponse fooResponse = FooResponse.newBuilder().build();
+ BarResponse barResponse = BarResponse.newBuilder().build();
+
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(fooDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(fooRequest),
+ EasyMock.same(FooResponse.getDefaultInstance()))).andReturn(fooResponse);
+ EasyMock.expect(mockChannel.callBlockingMethod(
+ EasyMock.same(barDescriptor),
+ EasyMock.same(mockController),
+ EasyMock.same(barRequest),
+ EasyMock.same(BarResponse.getDefaultInstance()))).andReturn(barResponse);
+ control.replay();
+
+ assertSame(fooResponse, stub.foo(mockController, fooRequest));
+ assertSame(barResponse, stub.bar(mockController, barRequest));
+ control.verify();
+ }
+
+ public void testNewReflectiveService() {
+ ServiceWithNoOuter.Interface impl =
+ control.createMock(ServiceWithNoOuter.Interface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ Service service = ServiceWithNoOuter.newReflectiveService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+ RpcCallback<Message> callback =
+ new RpcCallback<Message>() {
+ @Override
+ public void run(Message parameter) {
+ // No reason this should be run.
+ fail();
+ }
+ };
+ RpcCallback<TestAllTypes> specializedCallback =
+ RpcUtil.specializeCallback(callback);
+
+ impl.foo(EasyMock.same(controller), EasyMock.same(request),
+ EasyMock.same(specializedCallback));
+ EasyMock.expectLastCall();
+
+ control.replay();
+
+ service.callMethod(fooMethod, controller, request, callback);
+
+ control.verify();
+ }
+
+ public void testNewReflectiveBlockingService() throws ServiceException {
+ ServiceWithNoOuter.BlockingInterface impl =
+ control.createMock(ServiceWithNoOuter.BlockingInterface.class);
+ RpcController controller = control.createMock(RpcController.class);
+ BlockingService service =
+ ServiceWithNoOuter.newReflectiveBlockingService(impl);
+
+ MethodDescriptor fooMethod =
+ ServiceWithNoOuter.getDescriptor().findMethodByName("Foo");
+ MessageWithNoOuter request = MessageWithNoOuter.getDefaultInstance();
+
+ TestAllTypes expectedResponse = TestAllTypes.getDefaultInstance();
+ EasyMock.expect(impl.foo(EasyMock.same(controller), EasyMock.same(request)))
+ .andReturn(expectedResponse);
+
+ control.replay();
+
+ Message response =
+ service.callBlockingMethod(fooMethod, controller, request);
+ assertEquals(expectedResponse, response);
+
+ control.verify();
+ }
+
+ public void testNoGenericServices() throws Exception {
+ // Non-services should be usable.
+ UnittestNoGenericServices.TestMessage message =
+ UnittestNoGenericServices.TestMessage.newBuilder()
+ .setA(123)
+ .setExtension(UnittestNoGenericServices.testExtension, 456)
+ .build();
+ assertEquals(123, message.getA());
+ assertEquals(1, UnittestNoGenericServices.TestEnum.FOO.getNumber());
+
+ // Build a list of the class names nested in UnittestNoGenericServices.
+ String outerName = "google.protobuf.no_generic_services_test." +
+ "UnittestNoGenericServices";
+ Class<?> outerClass = Class.forName(outerName);
+
+ Set<String> innerClassNames = new HashSet<String>();
+ for (Class<?> innerClass : outerClass.getClasses()) {
+ String fullName = innerClass.getName();
+ // Figure out the unqualified name of the inner class.
+ // Note: Surprisingly, the full name of an inner class will be separated
+ // from the outer class name by a '$' rather than a '.'. This is not
+ // mentioned in the documentation for java.lang.Class. I don't want to
+ // make assumptions, so I'm just going to accept any character as the
+ // separator.
+ assertTrue(fullName.startsWith(outerName));
+
+ if (!Service.class.isAssignableFrom(innerClass) &&
+ !Message.class.isAssignableFrom(innerClass) &&
+ !ProtocolMessageEnum.class.isAssignableFrom(innerClass)) {
+ // Ignore any classes not generated by the base code generator.
+ continue;
+ }
+
+ innerClassNames.add(fullName.substring(outerName.length() + 1));
+ }
+
+ // No service class should have been generated.
+ assertTrue(innerClassNames.contains("TestMessage"));
+ assertTrue(innerClassNames.contains("TestEnum"));
+ assertFalse(innerClassNames.contains("TestService"));
+
+ // But descriptors are there.
+ FileDescriptor file = UnittestNoGenericServices.getDescriptor();
+ assertEquals(1, file.getServices().size());
+ assertEquals("TestService", file.getServices().get(0).getName());
+ assertEquals(1, file.getServices().get(0).getMethods().size());
+ assertEquals("Foo",
+ file.getServices().get(0).getMethods().get(0).getName());
+ }
+
+
+
+ // =================================================================
+
+ /**
+ * wrapsCallback() is an EasyMock argument predicate. wrapsCallback(c)
+ * matches a callback if calling that callback causes c to be called.
+ * In other words, c wraps the given callback.
+ */
+ private <Type extends Message> RpcCallback<Type> wrapsCallback(
+ MockCallback<?> callback) {
+ EasyMock.reportMatcher(new WrapsCallback(callback));
+ return null;
+ }
+
+ /** The parameter to wrapsCallback() must be a MockCallback. */
+ private static class MockCallback<Type extends Message>
+ implements RpcCallback<Type> {
+ private boolean called = false;
+
+ public boolean isCalled() { return called; }
+
+ public void reset() { called = false; }
+ @Override
+ public void run(Type message) {
+ called = true; }
+ }
+
+ /** Implementation of the wrapsCallback() argument matcher. */
+ private static class WrapsCallback implements IArgumentMatcher {
+ private MockCallback<?> callback;
+
+ public WrapsCallback(MockCallback<?> callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean matches(Object actual) {
+ if (!(actual instanceof RpcCallback)) {
+ return false;
+ }
+ RpcCallback actualCallback = (RpcCallback)actual;
+
+ callback.reset();
+ actualCallback.run(null);
+ return callback.isCalled();
+ }
+
+ @Override
+ public void appendTo(StringBuffer buffer) {
+ buffer.append("wrapsCallback(mockCallback)");
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java
new file mode 100644
index 0000000000..e3a8d4f408
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java
@@ -0,0 +1,155 @@
+// 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 protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link SingleFieldBuilderV3}. This tests basic functionality.
+ * More extensive testing is provided via other tests that exercise the
+ * builder.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class SingleFieldBuilderV3Test extends TestCase {
+
+ public void testBasicUseAndInvalidations() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ assertEquals(TestAllTypes.getDefaultInstance(),
+ builder.getBuilder().buildPartial());
+ assertEquals(0, mockParent.getInvalidationCount());
+
+ builder.getBuilder().setOptionalInt32(10);
+ assertEquals(0, mockParent.getInvalidationCount());
+ TestAllTypes message = builder.build();
+ assertEquals(10, message.getOptionalInt32());
+
+ // Test that we receive invalidations now that build has been called.
+ assertEquals(0, mockParent.getInvalidationCount());
+ builder.getBuilder().setOptionalInt32(20);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ // Test that we don't keep getting invalidations on every change
+ builder.getBuilder().setOptionalInt32(30);
+ assertEquals(1, mockParent.getInvalidationCount());
+
+ }
+
+ public void testSetMessage() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertEquals(0, builder.getMessage().getOptionalInt32());
+
+ // Update message using the builder
+ builder.getBuilder().setOptionalInt32(1);
+ assertEquals(0, mockParent.getInvalidationCount());
+ assertEquals(1, builder.getBuilder().getOptionalInt32());
+ assertEquals(1, builder.getMessage().getOptionalInt32());
+ builder.build();
+ builder.getBuilder().setOptionalInt32(2);
+ assertEquals(2, builder.getBuilder().getOptionalInt32());
+ assertEquals(2, builder.getMessage().getOptionalInt32());
+
+ // Make sure message stays cached
+ assertSame(builder.getMessage(), builder.getMessage());
+ }
+
+ public void testClear() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+ builder.setMessage(TestAllTypes.newBuilder().setOptionalInt32(0).build());
+ assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ builder.clear();
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+ builder.getBuilder().setOptionalInt32(1);
+ assertNotSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ builder.clear();
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+ }
+
+ public void testMerge() {
+ TestUtil.MockBuilderParent mockParent = new TestUtil.MockBuilderParent();
+ SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder> builder =
+ new SingleFieldBuilderV3<TestAllTypes, TestAllTypes.Builder,
+ TestAllTypesOrBuilder>(
+ TestAllTypes.getDefaultInstance(),
+ mockParent,
+ false);
+
+ // Merge into default field.
+ builder.mergeFrom(TestAllTypes.getDefaultInstance());
+ assertSame(TestAllTypes.getDefaultInstance(), builder.getMessage());
+
+ // Merge into non-default field on existing builder.
+ builder.getBuilder().setOptionalInt32(2);
+ builder.mergeFrom(TestAllTypes.newBuilder()
+ .setOptionalDouble(4.0)
+ .buildPartial());
+ assertEquals(2, builder.getMessage().getOptionalInt32());
+ assertEquals(4.0, builder.getMessage().getOptionalDouble());
+
+ // Merge into non-default field on existing message
+ builder.setMessage(TestAllTypes.newBuilder()
+ .setOptionalInt32(10)
+ .buildPartial());
+ builder.mergeFrom(TestAllTypes.newBuilder()
+ .setOptionalDouble(5.0)
+ .buildPartial());
+ assertEquals(10, builder.getMessage().getOptionalInt32());
+ assertEquals(5.0, builder.getMessage().getOptionalDouble());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
new file mode 100644
index 0000000000..a7f8342d13
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
@@ -0,0 +1,422 @@
+// 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.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import junit.framework.TestCase;
+
+/**
+ * @author darick@google.com Darick Tong
+ */
+public class SmallSortedMapTest extends TestCase {
+ // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
+ // here for JDK 1.5 users.
+ private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
+ private final K key;
+ private V value;
+
+ SimpleEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry))
+ return false;
+ Map.Entry e = (Map.Entry) o;
+ return eq(key, e.getKey()) && eq(value, e.getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return ((key == null) ? 0 : key.hashCode()) ^
+ ((value == null) ? 0 : value.hashCode());
+ }
+ }
+
+ public void testPutAndGetArrayEntriesOnly() {
+ runPutAndGetTest(3);
+ }
+
+ public void testPutAndGetOverflowEntries() {
+ runPutAndGetTest(6);
+ }
+
+ private void runPutAndGetTest(int numElements) {
+ // Test with even and odd arraySize
+ SmallSortedMap<Integer, Integer> map1 =
+ SmallSortedMap.newInstanceForTest(3);
+ SmallSortedMap<Integer, Integer> map2 =
+ SmallSortedMap.newInstanceForTest(4);
+ SmallSortedMap<Integer, Integer> map3 =
+ SmallSortedMap.newInstanceForTest(3);
+ SmallSortedMap<Integer, Integer> map4 =
+ SmallSortedMap.newInstanceForTest(4);
+
+ // Test with puts in ascending order.
+ for (int i = 0; i < numElements; i++) {
+ assertNull(map1.put(i, i + 1));
+ assertNull(map2.put(i, i + 1));
+ }
+ // Test with puts in descending order.
+ for (int i = numElements - 1; i >= 0; i--) {
+ assertNull(map3.put(i, i + 1));
+ assertNull(map4.put(i, i + 1));
+ }
+
+ assertEquals(Math.min(3, numElements), map1.getNumArrayEntries());
+ assertEquals(Math.min(4, numElements), map2.getNumArrayEntries());
+ assertEquals(Math.min(3, numElements), map3.getNumArrayEntries());
+ assertEquals(Math.min(4, numElements), map4.getNumArrayEntries());
+
+ List<SmallSortedMap<Integer, Integer>> allMaps =
+ new ArrayList<SmallSortedMap<Integer, Integer>>();
+ allMaps.add(map1);
+ allMaps.add(map2);
+ allMaps.add(map3);
+ allMaps.add(map4);
+
+ for (SmallSortedMap<Integer, Integer> map : allMaps) {
+ assertEquals(numElements, map.size());
+ for (int i = 0; i < numElements; i++) {
+ assertEquals(new Integer(i + 1), map.get(i));
+ }
+ }
+
+ assertEquals(map1, map2);
+ assertEquals(map2, map3);
+ assertEquals(map3, map4);
+ }
+
+ public void testReplacingPut() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ assertNull(map.remove(i + 1));
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 1), map.put(i, i + 2));
+ }
+ }
+
+ public void testRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ assertNull(map.remove(i + 1));
+ }
+
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(3, map.getNumOverflowEntries());
+ assertEquals(6, map.size());
+ assertEquals(makeSortedKeySet(0, 1, 2, 3, 4, 5), map.keySet());
+
+ assertEquals(new Integer(2), map.remove(1));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(2, map.getNumOverflowEntries());
+ assertEquals(5, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 3, 4, 5), map.keySet());
+
+ assertEquals(new Integer(5), map.remove(4));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(1, map.getNumOverflowEntries());
+ assertEquals(4, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 3, 5), map.keySet());
+
+ assertEquals(new Integer(4), map.remove(3));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(3, map.size());
+ assertEquals(makeSortedKeySet(0, 2, 5), map.keySet());
+
+ assertNull(map.remove(3));
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(3, map.size());
+
+ assertEquals(new Integer(1), map.remove(0));
+ assertEquals(2, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(2, map.size());
+ }
+
+ public void testClear() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.clear();
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testGetArrayEntryAndOverflowEntries() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ assertEquals(3, map.getNumArrayEntries());
+ for (int i = 0; i < 3; i++) {
+ Map.Entry<Integer, Integer> entry = map.getArrayEntryAt(i);
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ Iterator<Map.Entry<Integer, Integer>> it =
+ map.getOverflowEntries().iterator();
+ for (int i = 3; i < 6; i++) {
+ assertTrue(it.hasNext());
+ Map.Entry<Integer, Integer> entry = it.next();
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ assertFalse(it.hasNext());
+ }
+
+ public void testEntrySetContains() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(
+ entrySet.contains(new SimpleEntry<Integer, Integer>(i, i + 1)));
+ assertFalse(
+ entrySet.contains(new SimpleEntry<Integer, Integer>(i, i)));
+ }
+ }
+
+ public void testEntrySetAdd() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry =
+ new SimpleEntry<Integer, Integer>(i, i + 1);
+ assertTrue(entrySet.add(entry));
+ assertFalse(entrySet.add(entry));
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 1), map.get(i));
+ }
+ assertEquals(3, map.getNumArrayEntries());
+ assertEquals(3, map.getNumOverflowEntries());
+ assertEquals(6, map.size());
+ }
+
+ public void testEntrySetRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry =
+ new SimpleEntry<Integer, Integer>(i, i + 1);
+ assertTrue(entrySet.remove(entry));
+ assertFalse(entrySet.remove(entry));
+ }
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testEntrySetClear() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.entrySet().clear();
+ assertTrue(map.isEmpty());
+ assertEquals(0, map.getNumArrayEntries());
+ assertEquals(0, map.getNumOverflowEntries());
+ assertEquals(0, map.size());
+ }
+
+ public void testEntrySetIteratorNext() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(it.hasNext());
+ Map.Entry<Integer, Integer> entry = it.next();
+ assertEquals(new Integer(i), entry.getKey());
+ assertEquals(new Integer(i + 1), entry.getValue());
+ }
+ assertFalse(it.hasNext());
+ }
+
+ public void testEntrySetIteratorRemove() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ assertTrue(map.containsKey(i));
+ it.next();
+ it.remove();
+ assertFalse(map.containsKey(i));
+ assertEquals(6 - i - 1, map.size());
+ }
+ }
+
+ public void testMapEntryModification() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
+ for (int i = 0; i < 6; i++) {
+ Map.Entry<Integer, Integer> entry = it.next();
+ entry.setValue(i + 23);
+ }
+ for (int i = 0; i < 6; i++) {
+ assertEquals(new Integer(i + 23), map.get(i));
+ }
+ }
+
+ public void testMakeImmutable() {
+ SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
+ for (int i = 0; i < 6; i++) {
+ assertNull(map.put(i, i + 1));
+ }
+ map.makeImmutable();
+ assertEquals(new Integer(1), map.get(0));
+ assertEquals(6, map.size());
+
+ try {
+ map.put(23, 23);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Map<Integer, Integer> other = new HashMap<Integer, Integer>();
+ other.put(23, 23);
+ try {
+ map.putAll(other);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ map.remove(0);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ try {
+ map.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
+ try {
+ entrySet.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Iterator<Map.Entry<Integer, Integer>> it = entrySet.iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, Integer> entry = it.next();
+ try {
+ entry.setValue(0);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ try {
+ it.remove();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+
+ Set<Integer> keySet = map.keySet();
+ try {
+ keySet.clear();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+
+ Iterator<Integer> keys = keySet.iterator();
+ while (keys.hasNext()) {
+ Integer key = keys.next();
+ try {
+ keySet.remove(key);
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ try {
+ keys.remove();
+ fail("Expected UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
+ }
+
+ private Set<Integer> makeSortedKeySet(Integer... keys) {
+ return new TreeSet<Integer>(Arrays.<Integer>asList(keys));
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
new file mode 100644
index 0000000000..2c60fe0e1b
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -0,0 +1,96 @@
+// 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 junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when
+ * compiling protocol buffers that have names that would otherwise conflict
+ * if not fully qualified (like @Deprecated and @Override).
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class TestBadIdentifiers extends TestCase {
+
+ public void testCompilation() {
+ // If this compiles, it means the generation was correct.
+ TestBadIdentifiersProto.Deprecated.newBuilder();
+ TestBadIdentifiersProto.Override.newBuilder();
+ }
+
+ public void testGetDescriptor() {
+ Descriptors.FileDescriptor fileDescriptor =
+ TestBadIdentifiersProto.getDescriptor();
+ String descriptorField = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor protoDescriptor = TestBadIdentifiersProto.Descriptor
+ .getDefaultInstance().getDescriptorForType();
+ String nestedDescriptorField = TestBadIdentifiersProto.Descriptor
+ .NestedDescriptor.getDefaultInstance().getDescriptor();
+ Descriptors.Descriptor nestedProtoDescriptor = TestBadIdentifiersProto
+ .Descriptor.NestedDescriptor.getDefaultInstance()
+ .getDescriptorForType();
+ }
+
+ public void testConflictingFieldNames() throws Exception {
+ TestBadIdentifiersProto.TestConflictingFieldNames message =
+ TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance();
+ // Make sure generated accessors are properly named.
+ assertEquals(0, message.getInt32Field1Count());
+ assertEquals(0, message.getEnumField2Count());
+ assertEquals(0, message.getStringField3Count());
+ assertEquals(0, message.getBytesField4Count());
+ assertEquals(0, message.getMessageField5Count());
+
+ assertEquals(0, message.getInt32FieldCount11());
+ assertEquals(0, message.getEnumFieldCount12().getNumber());
+ assertEquals("", message.getStringFieldCount13());
+ assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
+ assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
+
+ assertEquals(0, message.getInt32Field21Count());
+ assertEquals(0, message.getEnumField22Count());
+ assertEquals(0, message.getStringField23Count());
+ assertEquals(0, message.getBytesField24Count());
+ assertEquals(0, message.getMessageField25Count());
+
+ assertEquals(0, message.getInt32Field1List().size());
+ assertEquals(0, message.getInt32FieldList31());
+
+ assertEquals(0, message.getInt64FieldCount());
+ assertEquals(0L, message.getExtension(
+ TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue());
+ assertEquals(0L, message.getExtension(
+ TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
+
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtil.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtil.java
new file mode 100644
index 0000000000..c1bd21db5c
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -0,0 +1,3866 @@
+// 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 static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+import static protobuf_unittest.UnittestProto.OptionalGroup_extension;
+import static protobuf_unittest.UnittestProto.RepeatedGroup_extension;
+import static protobuf_unittest.UnittestProto.defaultBoolExtension;
+import static protobuf_unittest.UnittestProto.defaultBytesExtension;
+import static protobuf_unittest.UnittestProto.defaultCordExtension;
+import static protobuf_unittest.UnittestProto.defaultDoubleExtension;
+import static protobuf_unittest.UnittestProto.defaultFixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultFixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultFloatExtension;
+import static protobuf_unittest.UnittestProto.defaultForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultImportEnumExtension;
+// The static imports are to avoid 100+ char lines. The following is roughly equivalent to
+// import static protobuf_unittest.UnittestProto.*;
+import static protobuf_unittest.UnittestProto.defaultInt32Extension;
+import static protobuf_unittest.UnittestProto.defaultInt64Extension;
+import static protobuf_unittest.UnittestProto.defaultNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.defaultSfixed32Extension;
+import static protobuf_unittest.UnittestProto.defaultSfixed64Extension;
+import static protobuf_unittest.UnittestProto.defaultSint32Extension;
+import static protobuf_unittest.UnittestProto.defaultSint64Extension;
+import static protobuf_unittest.UnittestProto.defaultStringExtension;
+import static protobuf_unittest.UnittestProto.defaultStringPieceExtension;
+import static protobuf_unittest.UnittestProto.defaultUint32Extension;
+import static protobuf_unittest.UnittestProto.defaultUint64Extension;
+import static protobuf_unittest.UnittestProto.oneofBytesExtension;
+import static protobuf_unittest.UnittestProto.oneofNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.oneofStringExtension;
+import static protobuf_unittest.UnittestProto.oneofUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalBoolExtension;
+import static protobuf_unittest.UnittestProto.optionalBytesExtension;
+import static protobuf_unittest.UnittestProto.optionalCordExtension;
+import static protobuf_unittest.UnittestProto.optionalDoubleExtension;
+import static protobuf_unittest.UnittestProto.optionalFixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalFixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalFloatExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalGroupExtension;
+import static protobuf_unittest.UnittestProto.optionalImportEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalInt32Extension;
+import static protobuf_unittest.UnittestProto.optionalInt64Extension;
+import static protobuf_unittest.UnittestProto.optionalLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.optionalNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalPublicImportMessageExtension;
+import static protobuf_unittest.UnittestProto.optionalSfixed32Extension;
+import static protobuf_unittest.UnittestProto.optionalSfixed64Extension;
+import static protobuf_unittest.UnittestProto.optionalSint32Extension;
+import static protobuf_unittest.UnittestProto.optionalSint64Extension;
+import static protobuf_unittest.UnittestProto.optionalStringExtension;
+import static protobuf_unittest.UnittestProto.optionalStringPieceExtension;
+import static protobuf_unittest.UnittestProto.optionalUint32Extension;
+import static protobuf_unittest.UnittestProto.optionalUint64Extension;
+import static protobuf_unittest.UnittestProto.packedBoolExtension;
+import static protobuf_unittest.UnittestProto.packedDoubleExtension;
+import static protobuf_unittest.UnittestProto.packedEnumExtension;
+import static protobuf_unittest.UnittestProto.packedFixed32Extension;
+import static protobuf_unittest.UnittestProto.packedFixed64Extension;
+import static protobuf_unittest.UnittestProto.packedFloatExtension;
+import static protobuf_unittest.UnittestProto.packedInt32Extension;
+import static protobuf_unittest.UnittestProto.packedInt64Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.packedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.packedSint32Extension;
+import static protobuf_unittest.UnittestProto.packedSint64Extension;
+import static protobuf_unittest.UnittestProto.packedUint32Extension;
+import static protobuf_unittest.UnittestProto.packedUint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedBoolExtension;
+import static protobuf_unittest.UnittestProto.repeatedBytesExtension;
+import static protobuf_unittest.UnittestProto.repeatedCordExtension;
+import static protobuf_unittest.UnittestProto.repeatedDoubleExtension;
+import static protobuf_unittest.UnittestProto.repeatedFixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedFixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedFloatExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedForeignMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedGroupExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedImportMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedInt32Extension;
+import static protobuf_unittest.UnittestProto.repeatedInt64Extension;
+import static protobuf_unittest.UnittestProto.repeatedLazyMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedEnumExtension;
+import static protobuf_unittest.UnittestProto.repeatedNestedMessageExtension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSfixed64Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedSint64Extension;
+import static protobuf_unittest.UnittestProto.repeatedStringExtension;
+import static protobuf_unittest.UnittestProto.repeatedStringPieceExtension;
+import static protobuf_unittest.UnittestProto.repeatedUint32Extension;
+import static protobuf_unittest.UnittestProto.repeatedUint64Extension;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLiteOrBuilder;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import com.google.protobuf.test.UnittestImport.ImportEnum;
+import com.google.protobuf.test.UnittestImport.ImportMessage;
+import com.google.protobuf.test.UnittestImportPublic.PublicImportMessage;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.ForeignMessage;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllExtensionsOrBuilder;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import protobuf_unittest.UnittestProto.TestUnpackedTypes;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import junit.framework.Assert;
+
+/**
+ * Contains methods for setting all fields of {@code TestAllTypes} to
+ * some values as well as checking that all the fields are set to those values.
+ * These are useful for testing various protocol message features, e.g.
+ * set all fields of a message, serialize it, parse it, and check that all
+ * fields are set.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ *
+ * @author kenton@google.com Kenton Varda
+ */
+public final class TestUtil {
+ private TestUtil() {}
+
+ /** Helper to convert a String to ByteString. */
+ static ByteString toBytes(String str) {
+ return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+ }
+
+ /**
+ * Dirties the message by resetting the momoized serialized size.
+ */
+ public static void resetMemoizedSize(AbstractMessage message) {
+ message.memoizedSize = -1;
+ }
+
+ /**
+ * Get a {@code TestAllTypes} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes getAllSet() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder.build();
+ }
+
+ /**
+ * Get a {@code TestAllTypes.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}.
+ */
+ public static TestAllTypes.Builder getAllSetBuilder() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
+ * Get a {@code TestAllExtensions} with all fields set as they would be by
+ * {@link #setAllExtensions(TestAllExtensions.Builder)}.
+ */
+ public static TestAllExtensions getAllExtensionsSet() {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestPackedTypes getPackedSet() {
+ TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
+ setPackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestUnpackedTypes getUnpackedSet() {
+ TestUnpackedTypes.Builder builder = TestUnpackedTypes.newBuilder();
+ setUnpackedFields(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensions getPackedExtensionsSet() {
+ TestPackedExtensions.Builder builder = TestPackedExtensions.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}.
+ */
+ public static void setAllFields(TestAllTypes.Builder message) {
+ message.setOptionalInt32 (101);
+ message.setOptionalInt64 (102);
+ message.setOptionalUint32 (103);
+ message.setOptionalUint64 (104);
+ message.setOptionalSint32 (105);
+ message.setOptionalSint64 (106);
+ message.setOptionalFixed32 (107);
+ message.setOptionalFixed64 (108);
+ message.setOptionalSfixed32(109);
+ message.setOptionalSfixed64(110);
+ message.setOptionalFloat (111);
+ message.setOptionalDouble (112);
+ message.setOptionalBool (true);
+ message.setOptionalString ("115");
+ message.setOptionalBytes (toBytes("116"));
+
+ message.setOptionalGroup(
+ TestAllTypes.OptionalGroup.newBuilder().setA(117).build());
+ message.setOptionalNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setOptionalForeignMessage(
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setOptionalImportMessage(
+ ImportMessage.newBuilder().setD(120).build());
+ message.setOptionalPublicImportMessage(
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setOptionalLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setOptionalNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.setOptionalImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.setOptionalStringPiece("124");
+ message.setOptionalCord("125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedInt32 (201);
+ message.addRepeatedInt64 (202);
+ message.addRepeatedUint32 (203);
+ message.addRepeatedUint64 (204);
+ message.addRepeatedSint32 (205);
+ message.addRepeatedSint64 (206);
+ message.addRepeatedFixed32 (207);
+ message.addRepeatedFixed64 (208);
+ message.addRepeatedSfixed32(209);
+ message.addRepeatedSfixed64(210);
+ message.addRepeatedFloat (211);
+ message.addRepeatedDouble (212);
+ message.addRepeatedBool (true);
+ message.addRepeatedString ("215");
+ message.addRepeatedBytes (toBytes("216"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(217).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(220).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAR);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAR);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAR);
+
+ message.addRepeatedStringPiece("224");
+ message.addRepeatedCord("225");
+
+ // Add a second one of each field.
+ message.addRepeatedInt32 (301);
+ message.addRepeatedInt64 (302);
+ message.addRepeatedUint32 (303);
+ message.addRepeatedUint64 (304);
+ message.addRepeatedSint32 (305);
+ message.addRepeatedSint64 (306);
+ message.addRepeatedFixed32 (307);
+ message.addRepeatedFixed64 (308);
+ message.addRepeatedSfixed32(309);
+ message.addRepeatedSfixed64(310);
+ message.addRepeatedFloat (311);
+ message.addRepeatedDouble (312);
+ message.addRepeatedBool (false);
+ message.addRepeatedString ("315");
+ message.addRepeatedBytes (toBytes("316"));
+
+ message.addRepeatedGroup(
+ TestAllTypes.RepeatedGroup.newBuilder().setA(317).build());
+ message.addRepeatedNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addRepeatedForeignMessage(
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addRepeatedImportMessage(
+ ImportMessage.newBuilder().setD(320).build());
+ message.addRepeatedLazyMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addRepeatedNestedEnum (TestAllTypes.NestedEnum.BAZ);
+ message.addRepeatedForeignEnum(ForeignEnum.FOREIGN_BAZ);
+ message.addRepeatedImportEnum (ImportEnum.IMPORT_BAZ);
+
+ message.addRepeatedStringPiece("324");
+ message.addRepeatedCord("325");
+
+ // -----------------------------------------------------------------
+
+ message.setDefaultInt32 (401);
+ message.setDefaultInt64 (402);
+ message.setDefaultUint32 (403);
+ message.setDefaultUint64 (404);
+ message.setDefaultSint32 (405);
+ message.setDefaultSint64 (406);
+ message.setDefaultFixed32 (407);
+ message.setDefaultFixed64 (408);
+ message.setDefaultSfixed32(409);
+ message.setDefaultSfixed64(410);
+ message.setDefaultFloat (411);
+ message.setDefaultDouble (412);
+ message.setDefaultBool (false);
+ message.setDefaultString ("415");
+ message.setDefaultBytes (toBytes("416"));
+
+ message.setDefaultNestedEnum (TestAllTypes.NestedEnum.FOO);
+ message.setDefaultForeignEnum(ForeignEnum.FOREIGN_FOO);
+ message.setDefaultImportEnum (ImportEnum.IMPORT_FOO);
+
+ message.setDefaultStringPiece("424");
+ message.setDefaultCord("425");
+
+ message.setOneofUint32(601);
+ message.setOneofNestedMessage(
+ TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+ message.setOneofString("603");
+ message.setOneofBytes(toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}.
+ */
+ public static void modifyRepeatedFields(TestAllTypes.Builder message) {
+ message.setRepeatedInt32 (1, 501);
+ message.setRepeatedInt64 (1, 502);
+ message.setRepeatedUint32 (1, 503);
+ message.setRepeatedUint64 (1, 504);
+ message.setRepeatedSint32 (1, 505);
+ message.setRepeatedSint64 (1, 506);
+ message.setRepeatedFixed32 (1, 507);
+ message.setRepeatedFixed64 (1, 508);
+ message.setRepeatedSfixed32(1, 509);
+ message.setRepeatedSfixed64(1, 510);
+ message.setRepeatedFloat (1, 511);
+ message.setRepeatedDouble (1, 512);
+ message.setRepeatedBool (1, true);
+ message.setRepeatedString (1, "515");
+ message.setRepeatedBytes (1, toBytes("516"));
+
+ message.setRepeatedGroup(1,
+ TestAllTypes.RepeatedGroup.newBuilder().setA(517).build());
+ message.setRepeatedNestedMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setRepeatedForeignMessage(1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setRepeatedImportMessage(1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setRepeatedLazyMessage(1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setRepeatedNestedEnum (1, TestAllTypes.NestedEnum.FOO);
+ message.setRepeatedForeignEnum(1, ForeignEnum.FOREIGN_FOO);
+ message.setRepeatedImportEnum (1, ImportEnum.IMPORT_FOO);
+
+ message.setRepeatedStringPiece(1, "524");
+ message.setRepeatedCord(1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}.
+ */
+ public static void assertAllFieldsSet(TestAllTypesOrBuilder message) {
+ Assert.assertTrue(message.hasOptionalInt32 ());
+ Assert.assertTrue(message.hasOptionalInt64 ());
+ Assert.assertTrue(message.hasOptionalUint32 ());
+ Assert.assertTrue(message.hasOptionalUint64 ());
+ Assert.assertTrue(message.hasOptionalSint32 ());
+ Assert.assertTrue(message.hasOptionalSint64 ());
+ Assert.assertTrue(message.hasOptionalFixed32 ());
+ Assert.assertTrue(message.hasOptionalFixed64 ());
+ Assert.assertTrue(message.hasOptionalSfixed32());
+ Assert.assertTrue(message.hasOptionalSfixed64());
+ Assert.assertTrue(message.hasOptionalFloat ());
+ Assert.assertTrue(message.hasOptionalDouble ());
+ Assert.assertTrue(message.hasOptionalBool ());
+ Assert.assertTrue(message.hasOptionalString ());
+ Assert.assertTrue(message.hasOptionalBytes ());
+
+ Assert.assertTrue(message.hasOptionalGroup ());
+ Assert.assertTrue(message.hasOptionalNestedMessage ());
+ Assert.assertTrue(message.hasOptionalForeignMessage());
+ Assert.assertTrue(message.hasOptionalImportMessage ());
+
+ Assert.assertTrue(message.getOptionalGroup ().hasA());
+ Assert.assertTrue(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertTrue(message.getOptionalForeignMessage().hasC());
+ Assert.assertTrue(message.getOptionalImportMessage ().hasD());
+
+ Assert.assertTrue(message.hasOptionalNestedEnum ());
+ Assert.assertTrue(message.hasOptionalForeignEnum());
+ Assert.assertTrue(message.hasOptionalImportEnum ());
+
+ Assert.assertTrue(message.hasOptionalStringPiece());
+ Assert.assertTrue(message.hasOptionalCord());
+
+ Assert.assertEquals(101 , message.getOptionalInt32 ());
+ Assert.assertEquals(102 , message.getOptionalInt64 ());
+ Assert.assertEquals(103 , message.getOptionalUint32 ());
+ Assert.assertEquals(104 , message.getOptionalUint64 ());
+ Assert.assertEquals(105 , message.getOptionalSint32 ());
+ Assert.assertEquals(106 , message.getOptionalSint64 ());
+ Assert.assertEquals(107 , message.getOptionalFixed32 ());
+ Assert.assertEquals(108 , message.getOptionalFixed64 ());
+ Assert.assertEquals(109 , message.getOptionalSfixed32());
+ Assert.assertEquals(110 , message.getOptionalSfixed64());
+ Assert.assertEquals(111 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(112 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(true , message.getOptionalBool ());
+ Assert.assertEquals("115", message.getOptionalString ());
+ Assert.assertEquals(toBytes("116"), message.getOptionalBytes());
+
+ Assert.assertEquals(117, message.getOptionalGroup ().getA());
+ Assert.assertEquals(118, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(119, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(120, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(126, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(127, message.getOptionalLazyMessage ().getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getOptionalNestedEnum());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getOptionalImportEnum());
+
+ Assert.assertEquals("124", message.getOptionalStringPiece());
+ Assert.assertEquals("125", message.getOptionalCord());
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202 , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204 , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206 , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208 , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210 , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211 , message.getRepeatedFloat (0), 0.0);
+ Assert.assertEquals(212 , message.getRepeatedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ Assert.assertEquals(301 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(302 , message.getRepeatedInt64 (1));
+ Assert.assertEquals(303 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(304 , message.getRepeatedUint64 (1));
+ Assert.assertEquals(305 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(306 , message.getRepeatedSint64 (1));
+ Assert.assertEquals(307 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(308 , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(309 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(310 , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(311 , message.getRepeatedFloat (1), 0.0);
+ Assert.assertEquals(312 , message.getRepeatedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getRepeatedBool (1));
+ Assert.assertEquals("315", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(317, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(318, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(319, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(320, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(327, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_BAZ, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("324", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("325", message.getRepeatedCord(1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasDefaultInt32 ());
+ Assert.assertTrue(message.hasDefaultInt64 ());
+ Assert.assertTrue(message.hasDefaultUint32 ());
+ Assert.assertTrue(message.hasDefaultUint64 ());
+ Assert.assertTrue(message.hasDefaultSint32 ());
+ Assert.assertTrue(message.hasDefaultSint64 ());
+ Assert.assertTrue(message.hasDefaultFixed32 ());
+ Assert.assertTrue(message.hasDefaultFixed64 ());
+ Assert.assertTrue(message.hasDefaultSfixed32());
+ Assert.assertTrue(message.hasDefaultSfixed64());
+ Assert.assertTrue(message.hasDefaultFloat ());
+ Assert.assertTrue(message.hasDefaultDouble ());
+ Assert.assertTrue(message.hasDefaultBool ());
+ Assert.assertTrue(message.hasDefaultString ());
+ Assert.assertTrue(message.hasDefaultBytes ());
+
+ Assert.assertTrue(message.hasDefaultNestedEnum ());
+ Assert.assertTrue(message.hasDefaultForeignEnum());
+ Assert.assertTrue(message.hasDefaultImportEnum ());
+
+ Assert.assertTrue(message.hasDefaultStringPiece());
+ Assert.assertTrue(message.hasDefaultCord());
+
+ Assert.assertEquals(401 , message.getDefaultInt32 ());
+ Assert.assertEquals(402 , message.getDefaultInt64 ());
+ Assert.assertEquals(403 , message.getDefaultUint32 ());
+ Assert.assertEquals(404 , message.getDefaultUint64 ());
+ Assert.assertEquals(405 , message.getDefaultSint32 ());
+ Assert.assertEquals(406 , message.getDefaultSint64 ());
+ Assert.assertEquals(407 , message.getDefaultFixed32 ());
+ Assert.assertEquals(408 , message.getDefaultFixed64 ());
+ Assert.assertEquals(409 , message.getDefaultSfixed32());
+ Assert.assertEquals(410 , message.getDefaultSfixed64());
+ Assert.assertEquals(411 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals(412 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(false, message.getDefaultBool ());
+ Assert.assertEquals("415", message.getDefaultString ());
+ Assert.assertEquals(toBytes("416"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getDefaultImportEnum());
+
+ Assert.assertEquals("424", message.getDefaultStringPiece());
+ Assert.assertEquals("425", message.getDefaultCord());
+
+ Assert.assertEquals(TestAllTypes.OneofFieldCase.ONEOF_BYTES, message.getOneofFieldCase());
+ Assert.assertFalse(message.hasOneofUint32());
+ Assert.assertFalse(message.hasOneofNestedMessage());
+ Assert.assertFalse(message.hasOneofString());
+ Assert.assertTrue(message.hasOneofBytes());
+
+ Assert.assertEquals(toBytes("604"), message.getOneofBytes());
+ }
+
+ // -------------------------------------------------------------------
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values.
+ */
+ public static void assertClear(TestAllTypesOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasOptionalInt32 ());
+ Assert.assertFalse(message.hasOptionalInt64 ());
+ Assert.assertFalse(message.hasOptionalUint32 ());
+ Assert.assertFalse(message.hasOptionalUint64 ());
+ Assert.assertFalse(message.hasOptionalSint32 ());
+ Assert.assertFalse(message.hasOptionalSint64 ());
+ Assert.assertFalse(message.hasOptionalFixed32 ());
+ Assert.assertFalse(message.hasOptionalFixed64 ());
+ Assert.assertFalse(message.hasOptionalSfixed32());
+ Assert.assertFalse(message.hasOptionalSfixed64());
+ Assert.assertFalse(message.hasOptionalFloat ());
+ Assert.assertFalse(message.hasOptionalDouble ());
+ Assert.assertFalse(message.hasOptionalBool ());
+ Assert.assertFalse(message.hasOptionalString ());
+ Assert.assertFalse(message.hasOptionalBytes ());
+
+ Assert.assertFalse(message.hasOptionalGroup ());
+ Assert.assertFalse(message.hasOptionalNestedMessage ());
+ Assert.assertFalse(message.hasOptionalForeignMessage());
+ Assert.assertFalse(message.hasOptionalImportMessage ());
+
+ Assert.assertFalse(message.hasOptionalNestedEnum ());
+ Assert.assertFalse(message.hasOptionalForeignEnum());
+ Assert.assertFalse(message.hasOptionalImportEnum ());
+
+ Assert.assertFalse(message.hasOptionalStringPiece());
+ Assert.assertFalse(message.hasOptionalCord());
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getOptionalInt32 ());
+ Assert.assertEquals(0 , message.getOptionalInt64 ());
+ Assert.assertEquals(0 , message.getOptionalUint32 ());
+ Assert.assertEquals(0 , message.getOptionalUint64 ());
+ Assert.assertEquals(0 , message.getOptionalSint32 ());
+ Assert.assertEquals(0 , message.getOptionalSint64 ());
+ Assert.assertEquals(0 , message.getOptionalFixed32 ());
+ Assert.assertEquals(0 , message.getOptionalFixed64 ());
+ Assert.assertEquals(0 , message.getOptionalSfixed32());
+ Assert.assertEquals(0 , message.getOptionalSfixed64());
+ Assert.assertEquals(0 , message.getOptionalFloat (), 0.0);
+ Assert.assertEquals(0 , message.getOptionalDouble (), 0.0);
+ Assert.assertEquals(false, message.getOptionalBool ());
+ Assert.assertEquals("" , message.getOptionalString ());
+ Assert.assertEquals(ByteString.EMPTY, message.getOptionalBytes());
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getOptionalGroup ().hasA());
+ Assert.assertFalse(message.getOptionalNestedMessage ().hasBb());
+ Assert.assertFalse(message.getOptionalForeignMessage ().hasC());
+ Assert.assertFalse(message.getOptionalImportMessage ().hasD());
+ Assert.assertFalse(message.getOptionalPublicImportMessage().hasE());
+ Assert.assertFalse(message.getOptionalLazyMessage ().hasBb());
+
+ Assert.assertEquals(0, message.getOptionalGroup ().getA());
+ Assert.assertEquals(0, message.getOptionalNestedMessage ().getBb());
+ Assert.assertEquals(0, message.getOptionalForeignMessage ().getC());
+ Assert.assertEquals(0, message.getOptionalImportMessage ().getD());
+ Assert.assertEquals(0, message.getOptionalPublicImportMessage().getE());
+ Assert.assertEquals(0, message.getOptionalLazyMessage ().getBb());
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getOptionalNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getOptionalForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getOptionalImportEnum());
+
+ Assert.assertEquals("", message.getOptionalStringPiece());
+ Assert.assertEquals("", message.getOptionalCord());
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedInt32Count ());
+ Assert.assertEquals(0, message.getRepeatedInt64Count ());
+ Assert.assertEquals(0, message.getRepeatedUint32Count ());
+ Assert.assertEquals(0, message.getRepeatedUint64Count ());
+ Assert.assertEquals(0, message.getRepeatedSint32Count ());
+ Assert.assertEquals(0, message.getRepeatedSint64Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(0, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(0, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(0, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(0, message.getRepeatedFloatCount ());
+ Assert.assertEquals(0, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(0, message.getRepeatedBoolCount ());
+ Assert.assertEquals(0, message.getRepeatedStringCount ());
+ Assert.assertEquals(0, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(0, message.getRepeatedGroupCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(0, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(0, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(0, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(0, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(0, message.getRepeatedCordCount());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasDefaultInt32 ());
+ Assert.assertFalse(message.hasDefaultInt64 ());
+ Assert.assertFalse(message.hasDefaultUint32 ());
+ Assert.assertFalse(message.hasDefaultUint64 ());
+ Assert.assertFalse(message.hasDefaultSint32 ());
+ Assert.assertFalse(message.hasDefaultSint64 ());
+ Assert.assertFalse(message.hasDefaultFixed32 ());
+ Assert.assertFalse(message.hasDefaultFixed64 ());
+ Assert.assertFalse(message.hasDefaultSfixed32());
+ Assert.assertFalse(message.hasDefaultSfixed64());
+ Assert.assertFalse(message.hasDefaultFloat ());
+ Assert.assertFalse(message.hasDefaultDouble ());
+ Assert.assertFalse(message.hasDefaultBool ());
+ Assert.assertFalse(message.hasDefaultString ());
+ Assert.assertFalse(message.hasDefaultBytes ());
+
+ Assert.assertFalse(message.hasDefaultNestedEnum ());
+ Assert.assertFalse(message.hasDefaultForeignEnum());
+ Assert.assertFalse(message.hasDefaultImportEnum ());
+
+ Assert.assertFalse(message.hasDefaultStringPiece());
+ Assert.assertFalse(message.hasDefaultCord());
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getDefaultInt32 ());
+ Assert.assertEquals( 42 , message.getDefaultInt64 ());
+ Assert.assertEquals( 43 , message.getDefaultUint32 ());
+ Assert.assertEquals( 44 , message.getDefaultUint64 ());
+ Assert.assertEquals(-45 , message.getDefaultSint32 ());
+ Assert.assertEquals( 46 , message.getDefaultSint64 ());
+ Assert.assertEquals( 47 , message.getDefaultFixed32 ());
+ Assert.assertEquals( 48 , message.getDefaultFixed64 ());
+ Assert.assertEquals( 49 , message.getDefaultSfixed32());
+ Assert.assertEquals(-50 , message.getDefaultSfixed64());
+ Assert.assertEquals( 51.5 , message.getDefaultFloat (), 0.0);
+ Assert.assertEquals( 52e3 , message.getDefaultDouble (), 0.0);
+ Assert.assertEquals(true , message.getDefaultBool ());
+ Assert.assertEquals("hello", message.getDefaultString ());
+ Assert.assertEquals(toBytes("world"), message.getDefaultBytes());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getDefaultNestedEnum ());
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getDefaultForeignEnum());
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getDefaultImportEnum());
+
+ Assert.assertEquals("abc", message.getDefaultStringPiece());
+ Assert.assertEquals("123", message.getDefaultCord());
+
+ Assert.assertFalse(message.hasOneofUint32());
+ Assert.assertFalse(message.hasOneofNestedMessage());
+ Assert.assertFalse(message.hasOneofString());
+ Assert.assertFalse(message.hasOneofBytes());
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields}
+ * followed by {@code modifyRepeatedFields}.
+ */
+ public static void assertRepeatedFieldsModified(
+ TestAllTypesOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedInt32Count ());
+ Assert.assertEquals(2, message.getRepeatedInt64Count ());
+ Assert.assertEquals(2, message.getRepeatedUint32Count ());
+ Assert.assertEquals(2, message.getRepeatedUint64Count ());
+ Assert.assertEquals(2, message.getRepeatedSint32Count ());
+ Assert.assertEquals(2, message.getRepeatedSint64Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed32Count ());
+ Assert.assertEquals(2, message.getRepeatedFixed64Count ());
+ Assert.assertEquals(2, message.getRepeatedSfixed32Count());
+ Assert.assertEquals(2, message.getRepeatedSfixed64Count());
+ Assert.assertEquals(2, message.getRepeatedFloatCount ());
+ Assert.assertEquals(2, message.getRepeatedDoubleCount ());
+ Assert.assertEquals(2, message.getRepeatedBoolCount ());
+ Assert.assertEquals(2, message.getRepeatedStringCount ());
+ Assert.assertEquals(2, message.getRepeatedBytesCount ());
+
+ Assert.assertEquals(2, message.getRepeatedGroupCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignMessageCount());
+ Assert.assertEquals(2, message.getRepeatedImportMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedLazyMessageCount ());
+ Assert.assertEquals(2, message.getRepeatedNestedEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedForeignEnumCount ());
+ Assert.assertEquals(2, message.getRepeatedImportEnumCount ());
+
+ Assert.assertEquals(2, message.getRepeatedStringPieceCount());
+ Assert.assertEquals(2, message.getRepeatedCordCount());
+
+ Assert.assertEquals(201 , message.getRepeatedInt32 (0));
+ Assert.assertEquals(202L , message.getRepeatedInt64 (0));
+ Assert.assertEquals(203 , message.getRepeatedUint32 (0));
+ Assert.assertEquals(204L , message.getRepeatedUint64 (0));
+ Assert.assertEquals(205 , message.getRepeatedSint32 (0));
+ Assert.assertEquals(206L , message.getRepeatedSint64 (0));
+ Assert.assertEquals(207 , message.getRepeatedFixed32 (0));
+ Assert.assertEquals(208L , message.getRepeatedFixed64 (0));
+ Assert.assertEquals(209 , message.getRepeatedSfixed32(0));
+ Assert.assertEquals(210L , message.getRepeatedSfixed64(0));
+ Assert.assertEquals(211F , message.getRepeatedFloat (0));
+ Assert.assertEquals(212D , message.getRepeatedDouble (0));
+ Assert.assertEquals(true , message.getRepeatedBool (0));
+ Assert.assertEquals("215", message.getRepeatedString (0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedBytes(0));
+
+ Assert.assertEquals(217, message.getRepeatedGroup (0).getA());
+ Assert.assertEquals(218, message.getRepeatedNestedMessage (0).getBb());
+ Assert.assertEquals(219, message.getRepeatedForeignMessage(0).getC());
+ Assert.assertEquals(220, message.getRepeatedImportMessage (0).getD());
+ Assert.assertEquals(227, message.getRepeatedLazyMessage (0).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.BAR, message.getRepeatedNestedEnum (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getRepeatedForeignEnum(0));
+ Assert.assertEquals(ImportEnum.IMPORT_BAR, message.getRepeatedImportEnum(0));
+
+ Assert.assertEquals("224", message.getRepeatedStringPiece(0));
+ Assert.assertEquals("225", message.getRepeatedCord(0));
+
+ // Actually verify the second (modified) elements now.
+ Assert.assertEquals(501 , message.getRepeatedInt32 (1));
+ Assert.assertEquals(502L , message.getRepeatedInt64 (1));
+ Assert.assertEquals(503 , message.getRepeatedUint32 (1));
+ Assert.assertEquals(504L , message.getRepeatedUint64 (1));
+ Assert.assertEquals(505 , message.getRepeatedSint32 (1));
+ Assert.assertEquals(506L , message.getRepeatedSint64 (1));
+ Assert.assertEquals(507 , message.getRepeatedFixed32 (1));
+ Assert.assertEquals(508L , message.getRepeatedFixed64 (1));
+ Assert.assertEquals(509 , message.getRepeatedSfixed32(1));
+ Assert.assertEquals(510L , message.getRepeatedSfixed64(1));
+ Assert.assertEquals(511F , message.getRepeatedFloat (1));
+ Assert.assertEquals(512D , message.getRepeatedDouble (1));
+ Assert.assertEquals(true , message.getRepeatedBool (1));
+ Assert.assertEquals("515", message.getRepeatedString (1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedBytes(1));
+
+ Assert.assertEquals(517, message.getRepeatedGroup (1).getA());
+ Assert.assertEquals(518, message.getRepeatedNestedMessage (1).getBb());
+ Assert.assertEquals(519, message.getRepeatedForeignMessage(1).getC());
+ Assert.assertEquals(520, message.getRepeatedImportMessage (1).getD());
+ Assert.assertEquals(527, message.getRepeatedLazyMessage (1).getBb());
+
+ Assert.assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_FOO, message.getRepeatedForeignEnum(1));
+ Assert.assertEquals(ImportEnum.IMPORT_FOO, message.getRepeatedImportEnum(1));
+
+ Assert.assertEquals("524", message.getRepeatedStringPiece(1));
+ Assert.assertEquals("525", message.getRepeatedCord(1));
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value.
+ */
+ public static void setPackedFields(TestPackedTypes.Builder message) {
+ message.addPackedInt32 (601);
+ message.addPackedInt64 (602);
+ message.addPackedUint32 (603);
+ message.addPackedUint64 (604);
+ message.addPackedSint32 (605);
+ message.addPackedSint64 (606);
+ message.addPackedFixed32 (607);
+ message.addPackedFixed64 (608);
+ message.addPackedSfixed32(609);
+ message.addPackedSfixed64(610);
+ message.addPackedFloat (611);
+ message.addPackedDouble (612);
+ message.addPackedBool (true);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addPackedInt32 (701);
+ message.addPackedInt64 (702);
+ message.addPackedUint32 (703);
+ message.addPackedUint64 (704);
+ message.addPackedSint32 (705);
+ message.addPackedSint64 (706);
+ message.addPackedFixed32 (707);
+ message.addPackedFixed64 (708);
+ message.addPackedSfixed32(709);
+ message.addPackedSfixed64(710);
+ message.addPackedFloat (711);
+ message.addPackedDouble (712);
+ message.addPackedBool (false);
+ message.addPackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Set every field of {@code message} to a unique value. Must correspond with
+ * the values applied by {@code setPackedFields}.
+ */
+ public static void setUnpackedFields(TestUnpackedTypes.Builder message) {
+ message.addUnpackedInt32 (601);
+ message.addUnpackedInt64 (602);
+ message.addUnpackedUint32 (603);
+ message.addUnpackedUint64 (604);
+ message.addUnpackedSint32 (605);
+ message.addUnpackedSint64 (606);
+ message.addUnpackedFixed32 (607);
+ message.addUnpackedFixed64 (608);
+ message.addUnpackedSfixed32(609);
+ message.addUnpackedSfixed64(610);
+ message.addUnpackedFloat (611);
+ message.addUnpackedDouble (612);
+ message.addUnpackedBool (true);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addUnpackedInt32 (701);
+ message.addUnpackedInt64 (702);
+ message.addUnpackedUint32 (703);
+ message.addUnpackedUint64 (704);
+ message.addUnpackedSint32 (705);
+ message.addUnpackedSint64 (706);
+ message.addUnpackedFixed32 (707);
+ message.addUnpackedFixed64 (708);
+ message.addUnpackedSfixed32(709);
+ message.addUnpackedSfixed64(710);
+ message.addUnpackedFloat (711);
+ message.addUnpackedDouble (712);
+ message.addUnpackedBool (false);
+ message.addUnpackedEnum (ForeignEnum.FOREIGN_BAZ);
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setPackedFields}.
+ */
+ public static void assertPackedFieldsSet(TestPackedTypes message) {
+ Assert.assertEquals(2, message.getPackedInt32Count ());
+ Assert.assertEquals(2, message.getPackedInt64Count ());
+ Assert.assertEquals(2, message.getPackedUint32Count ());
+ Assert.assertEquals(2, message.getPackedUint64Count ());
+ Assert.assertEquals(2, message.getPackedSint32Count ());
+ Assert.assertEquals(2, message.getPackedSint64Count ());
+ Assert.assertEquals(2, message.getPackedFixed32Count ());
+ Assert.assertEquals(2, message.getPackedFixed64Count ());
+ Assert.assertEquals(2, message.getPackedSfixed32Count());
+ Assert.assertEquals(2, message.getPackedSfixed64Count());
+ Assert.assertEquals(2, message.getPackedFloatCount ());
+ Assert.assertEquals(2, message.getPackedDoubleCount ());
+ Assert.assertEquals(2, message.getPackedBoolCount ());
+ Assert.assertEquals(2, message.getPackedEnumCount ());
+ Assert.assertEquals(601 , message.getPackedInt32 (0));
+ Assert.assertEquals(602 , message.getPackedInt64 (0));
+ Assert.assertEquals(603 , message.getPackedUint32 (0));
+ Assert.assertEquals(604 , message.getPackedUint64 (0));
+ Assert.assertEquals(605 , message.getPackedSint32 (0));
+ Assert.assertEquals(606 , message.getPackedSint64 (0));
+ Assert.assertEquals(607 , message.getPackedFixed32 (0));
+ Assert.assertEquals(608 , message.getPackedFixed64 (0));
+ Assert.assertEquals(609 , message.getPackedSfixed32(0));
+ Assert.assertEquals(610 , message.getPackedSfixed64(0));
+ Assert.assertEquals(611 , message.getPackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getPackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getPackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getPackedEnum(0));
+ Assert.assertEquals(701 , message.getPackedInt32 (1));
+ Assert.assertEquals(702 , message.getPackedInt64 (1));
+ Assert.assertEquals(703 , message.getPackedUint32 (1));
+ Assert.assertEquals(704 , message.getPackedUint64 (1));
+ Assert.assertEquals(705 , message.getPackedSint32 (1));
+ Assert.assertEquals(706 , message.getPackedSint64 (1));
+ Assert.assertEquals(707 , message.getPackedFixed32 (1));
+ Assert.assertEquals(708 , message.getPackedFixed64 (1));
+ Assert.assertEquals(709 , message.getPackedSfixed32(1));
+ Assert.assertEquals(710 , message.getPackedSfixed64(1));
+ Assert.assertEquals(711 , message.getPackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getPackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getPackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getPackedEnum(1));
+ }
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setUnpackedFields}.
+ */
+ public static void assertUnpackedFieldsSet(TestUnpackedTypes message) {
+ Assert.assertEquals(2, message.getUnpackedInt32Count ());
+ Assert.assertEquals(2, message.getUnpackedInt64Count ());
+ Assert.assertEquals(2, message.getUnpackedUint32Count ());
+ Assert.assertEquals(2, message.getUnpackedUint64Count ());
+ Assert.assertEquals(2, message.getUnpackedSint32Count ());
+ Assert.assertEquals(2, message.getUnpackedSint64Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed32Count ());
+ Assert.assertEquals(2, message.getUnpackedFixed64Count ());
+ Assert.assertEquals(2, message.getUnpackedSfixed32Count());
+ Assert.assertEquals(2, message.getUnpackedSfixed64Count());
+ Assert.assertEquals(2, message.getUnpackedFloatCount ());
+ Assert.assertEquals(2, message.getUnpackedDoubleCount ());
+ Assert.assertEquals(2, message.getUnpackedBoolCount ());
+ Assert.assertEquals(2, message.getUnpackedEnumCount ());
+ Assert.assertEquals(601 , message.getUnpackedInt32 (0));
+ Assert.assertEquals(602 , message.getUnpackedInt64 (0));
+ Assert.assertEquals(603 , message.getUnpackedUint32 (0));
+ Assert.assertEquals(604 , message.getUnpackedUint64 (0));
+ Assert.assertEquals(605 , message.getUnpackedSint32 (0));
+ Assert.assertEquals(606 , message.getUnpackedSint64 (0));
+ Assert.assertEquals(607 , message.getUnpackedFixed32 (0));
+ Assert.assertEquals(608 , message.getUnpackedFixed64 (0));
+ Assert.assertEquals(609 , message.getUnpackedSfixed32(0));
+ Assert.assertEquals(610 , message.getUnpackedSfixed64(0));
+ Assert.assertEquals(611 , message.getUnpackedFloat (0), 0.0);
+ Assert.assertEquals(612 , message.getUnpackedDouble (0), 0.0);
+ Assert.assertEquals(true , message.getUnpackedBool (0));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAR, message.getUnpackedEnum(0));
+ Assert.assertEquals(701 , message.getUnpackedInt32 (1));
+ Assert.assertEquals(702 , message.getUnpackedInt64 (1));
+ Assert.assertEquals(703 , message.getUnpackedUint32 (1));
+ Assert.assertEquals(704 , message.getUnpackedUint64 (1));
+ Assert.assertEquals(705 , message.getUnpackedSint32 (1));
+ Assert.assertEquals(706 , message.getUnpackedSint64 (1));
+ Assert.assertEquals(707 , message.getUnpackedFixed32 (1));
+ Assert.assertEquals(708 , message.getUnpackedFixed64 (1));
+ Assert.assertEquals(709 , message.getUnpackedSfixed32(1));
+ Assert.assertEquals(710 , message.getUnpackedSfixed64(1));
+ Assert.assertEquals(711 , message.getUnpackedFloat (1), 0.0);
+ Assert.assertEquals(712 , message.getUnpackedDouble (1), 0.0);
+ Assert.assertEquals(false, message.getUnpackedBool (1));
+ Assert.assertEquals(ForeignEnum.FOREIGN_BAZ, message.getUnpackedEnum(1));
+ }
+
+ // ===================================================================
+ // Like above, but for extensions
+
+ // Java gets confused with things like assertEquals(int, Integer): it can't
+ // decide whether to call assertEquals(int, int) or assertEquals(Object,
+ // Object). So we define these methods to help it.
+ private static void assertEqualsExactType(int a, int b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(long a, long b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(float a, float b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(double a, double b) {
+ Assert.assertEquals(a, b, 0.0);
+ }
+ private static void assertEqualsExactType(boolean a, boolean b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(String a, String b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ByteString a, ByteString b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(TestAllTypes.NestedEnum a,
+ TestAllTypes.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnum a, ForeignEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnum a, ImportEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(TestAllTypesLite.NestedEnum a,
+ TestAllTypesLite.NestedEnum b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ForeignEnumLite a,
+ ForeignEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
+ private static void assertEqualsExactType(ImportEnumLite a,
+ ImportEnumLite b) {
+ Assert.assertEquals(a, b);
+ }
+
+ /**
+ * Get an unmodifiable {@link ExtensionRegistry} containing all the
+ * extensions of {@code TestAllExtensions}.
+ */
+ public static ExtensionRegistry getExtensionRegistry() {
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ registerAllExtensions(registry);
+ return registry.getUnmodifiable();
+ }
+
+ /**
+ * Register all of {@code TestAllExtensions}'s extensions with the
+ * given {@link ExtensionRegistry}.
+ */
+ public static void registerAllExtensions(ExtensionRegistry registry) {
+ UnittestProto.registerAllExtensions(registry);
+ TestUtilLite.registerAllExtensionsLite(registry);
+ }
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensions.Builder message) {
+ message.setExtension(optionalInt32Extension , 101);
+ message.setExtension(optionalInt64Extension , 102L);
+ message.setExtension(optionalUint32Extension , 103);
+ message.setExtension(optionalUint64Extension , 104L);
+ message.setExtension(optionalSint32Extension , 105);
+ message.setExtension(optionalSint64Extension , 106L);
+ message.setExtension(optionalFixed32Extension , 107);
+ message.setExtension(optionalFixed64Extension , 108L);
+ message.setExtension(optionalSfixed32Extension, 109);
+ message.setExtension(optionalSfixed64Extension, 110L);
+ message.setExtension(optionalFloatExtension , 111F);
+ message.setExtension(optionalDoubleExtension , 112D);
+ message.setExtension(optionalBoolExtension , true);
+ message.setExtension(optionalStringExtension , "115");
+ message.setExtension(optionalBytesExtension , toBytes("116"));
+
+ message.setExtension(optionalGroupExtension,
+ OptionalGroup_extension.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtension,
+ ImportMessage.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtension,
+ PublicImportMessage.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setExtension(optionalNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.setExtension(optionalImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.setExtension(optionalStringPieceExtension, "124");
+ message.setExtension(optionalCordExtension, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32Extension , 201);
+ message.addExtension(repeatedInt64Extension , 202L);
+ message.addExtension(repeatedUint32Extension , 203);
+ message.addExtension(repeatedUint64Extension , 204L);
+ message.addExtension(repeatedSint32Extension , 205);
+ message.addExtension(repeatedSint64Extension , 206L);
+ message.addExtension(repeatedFixed32Extension , 207);
+ message.addExtension(repeatedFixed64Extension , 208L);
+ message.addExtension(repeatedSfixed32Extension, 209);
+ message.addExtension(repeatedSfixed64Extension, 210L);
+ message.addExtension(repeatedFloatExtension , 211F);
+ message.addExtension(repeatedDoubleExtension , 212D);
+ message.addExtension(repeatedBoolExtension , true);
+ message.addExtension(repeatedStringExtension , "215");
+ message.addExtension(repeatedBytesExtension , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAR);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAR);
+
+ message.addExtension(repeatedStringPieceExtension, "224");
+ message.addExtension(repeatedCordExtension, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32Extension , 301);
+ message.addExtension(repeatedInt64Extension , 302L);
+ message.addExtension(repeatedUint32Extension , 303);
+ message.addExtension(repeatedUint64Extension , 304L);
+ message.addExtension(repeatedSint32Extension , 305);
+ message.addExtension(repeatedSint64Extension , 306L);
+ message.addExtension(repeatedFixed32Extension , 307);
+ message.addExtension(repeatedFixed64Extension , 308L);
+ message.addExtension(repeatedSfixed32Extension, 309);
+ message.addExtension(repeatedSfixed64Extension, 310L);
+ message.addExtension(repeatedFloatExtension , 311F);
+ message.addExtension(repeatedDoubleExtension , 312D);
+ message.addExtension(repeatedBoolExtension , false);
+ message.addExtension(repeatedStringExtension , "315");
+ message.addExtension(repeatedBytesExtension , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtension,
+ RepeatedGroup_extension.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtension,
+ ForeignMessage.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtension,
+ ImportMessage.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addExtension(repeatedNestedEnumExtension, TestAllTypes.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ message.addExtension(repeatedImportEnumExtension, ImportEnum.IMPORT_BAZ);
+
+ message.addExtension(repeatedStringPieceExtension, "324");
+ message.addExtension(repeatedCordExtension, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32Extension , 401);
+ message.setExtension(defaultInt64Extension , 402L);
+ message.setExtension(defaultUint32Extension , 403);
+ message.setExtension(defaultUint64Extension , 404L);
+ message.setExtension(defaultSint32Extension , 405);
+ message.setExtension(defaultSint64Extension , 406L);
+ message.setExtension(defaultFixed32Extension , 407);
+ message.setExtension(defaultFixed64Extension , 408L);
+ message.setExtension(defaultSfixed32Extension, 409);
+ message.setExtension(defaultSfixed64Extension, 410L);
+ message.setExtension(defaultFloatExtension , 411F);
+ message.setExtension(defaultDoubleExtension , 412D);
+ message.setExtension(defaultBoolExtension , false);
+ message.setExtension(defaultStringExtension , "415");
+ message.setExtension(defaultBytesExtension , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtension, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(defaultImportEnumExtension, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(defaultStringPieceExtension, "424");
+ message.setExtension(defaultCordExtension, "425");
+
+ message.setExtension(oneofUint32Extension, 601);
+ message.setExtension(oneofNestedMessageExtension,
+ TestAllTypes.NestedMessage.newBuilder().setBb(602).build());
+ message.setExtension(oneofStringExtension, "603");
+ message.setExtension(oneofBytesExtension, toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensions.Builder message) {
+ message.setExtension(repeatedInt32Extension , 1, 501);
+ message.setExtension(repeatedInt64Extension , 1, 502L);
+ message.setExtension(repeatedUint32Extension , 1, 503);
+ message.setExtension(repeatedUint64Extension , 1, 504L);
+ message.setExtension(repeatedSint32Extension , 1, 505);
+ message.setExtension(repeatedSint64Extension , 1, 506L);
+ message.setExtension(repeatedFixed32Extension , 1, 507);
+ message.setExtension(repeatedFixed64Extension , 1, 508L);
+ message.setExtension(repeatedSfixed32Extension, 1, 509);
+ message.setExtension(repeatedSfixed64Extension, 1, 510L);
+ message.setExtension(repeatedFloatExtension , 1, 511F);
+ message.setExtension(repeatedDoubleExtension , 1, 512D);
+ message.setExtension(repeatedBoolExtension , 1, true);
+ message.setExtension(repeatedStringExtension , 1, "515");
+ message.setExtension(repeatedBytesExtension , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtension, 1,
+ RepeatedGroup_extension.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtension, 1,
+ ForeignMessage.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtension, 1,
+ ImportMessage.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtension, 1,
+ TestAllTypes.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setExtension(repeatedNestedEnumExtension , 1, TestAllTypes.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtension, 1, ForeignEnum.FOREIGN_FOO);
+ message.setExtension(repeatedImportEnumExtension , 1, ImportEnum.IMPORT_FOO);
+
+ message.setExtension(repeatedStringPieceExtension, 1, "524");
+ message.setExtension(repeatedCordExtension, 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(
+ TestAllExtensionsOrBuilder message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalInt64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalUint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSint64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtension ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtension ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtension ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtension ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(optionalCordExtension));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtension));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtension ).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtension ).getD());
+ assertEqualsExactType(126, message.getExtension(optionalPublicImportMessageExtension).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtension ).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtension));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtension));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_BAZ,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtension, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultInt64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultUint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSint64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtension ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtension ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtension ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertTrue(message.hasExtension(defaultCordExtension));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtension));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtension));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(TestAllExtensionsOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalInt64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalUint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSint64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtension ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtension ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtension ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtension ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(optionalCordExtension));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32Extension ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64Extension ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32Extension));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64Extension));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtension ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtension ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtension ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtension ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtension));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtension ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtension ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtension).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtension ).hasD());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtension ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtension ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtension).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtension ).getD());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(optionalForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(optionalImportEnumExtension));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtension));
+ assertEqualsExactType("", message.getExtension(optionalCordExtension));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtension));
+
+ // Repeated fields are empty via getExtension().size().
+ Assert.assertEquals(0, message.getExtension(repeatedInt32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedInt64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedUint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSint64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed32Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFixed64Extension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed32Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedSfixed64Extension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedFloatExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedDoubleExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBoolExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedStringExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedBytesExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedGroupExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignMessageExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedLazyMessageExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedNestedEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedForeignEnumExtension ).size());
+ Assert.assertEquals(0, message.getExtension(repeatedImportEnumExtension ).size());
+
+ Assert.assertEquals(0, message.getExtension(repeatedStringPieceExtension).size());
+ Assert.assertEquals(0, message.getExtension(repeatedCordExtension).size());
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultInt64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultUint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSint64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32Extension ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64Extension ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32Extension));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64Extension));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtension ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtension ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtension ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtension ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtension));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtension ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtension));
+ Assert.assertFalse(message.hasExtension(defaultCordExtension));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32Extension ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64Extension ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32Extension ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64Extension ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32Extension ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64Extension ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32Extension ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64Extension ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32Extension));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64Extension));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtension ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtension ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtension ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtension ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtension));
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtension ));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(defaultForeignEnumExtension));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(defaultImportEnumExtension));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtension));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtension));
+
+ Assert.assertFalse(message.hasExtension(oneofUint32Extension));
+ Assert.assertFalse(message.hasExtension(oneofNestedMessageExtension));
+ Assert.assertFalse(message.hasExtension(oneofStringExtension));
+ Assert.assertFalse(message.hasExtension(oneofBytesExtension));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtension ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtension));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtension));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32Extension , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64Extension , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32Extension , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64Extension , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32Extension , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64Extension , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32Extension , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64Extension , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32Extension, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64Extension, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtension , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtension , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtension, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtension , 0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtension , 0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtension, 0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtension , 0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtension , 0).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtension, 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(repeatedForeignEnumExtension, 0));
+ assertEqualsExactType(ImportEnum.IMPORT_BAR,
+ message.getExtension(repeatedImportEnumExtension, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtension, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtension, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32Extension , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64Extension , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32Extension , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64Extension , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32Extension , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64Extension , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32Extension , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64Extension , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32Extension, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64Extension, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtension , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtension , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtension , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtension , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtension, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtension , 1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtension , 1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtension, 1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtension , 1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtension , 1).getBb());
+
+ assertEqualsExactType(TestAllTypes.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtension, 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_FOO,
+ message.getExtension(repeatedForeignEnumExtension, 1));
+ assertEqualsExactType(ImportEnum.IMPORT_FOO,
+ message.getExtension(repeatedImportEnumExtension, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtension, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtension, 1));
+ }
+
+ public static void setPackedExtensions(TestPackedExtensions.Builder message) {
+ message.addExtension(packedInt32Extension , 601);
+ message.addExtension(packedInt64Extension , 602L);
+ message.addExtension(packedUint32Extension , 603);
+ message.addExtension(packedUint64Extension , 604L);
+ message.addExtension(packedSint32Extension , 605);
+ message.addExtension(packedSint64Extension , 606L);
+ message.addExtension(packedFixed32Extension , 607);
+ message.addExtension(packedFixed64Extension , 608L);
+ message.addExtension(packedSfixed32Extension, 609);
+ message.addExtension(packedSfixed64Extension, 610L);
+ message.addExtension(packedFloatExtension , 611F);
+ message.addExtension(packedDoubleExtension , 612D);
+ message.addExtension(packedBoolExtension , true);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32Extension , 701);
+ message.addExtension(packedInt64Extension , 702L);
+ message.addExtension(packedUint32Extension , 703);
+ message.addExtension(packedUint64Extension , 704L);
+ message.addExtension(packedSint32Extension , 705);
+ message.addExtension(packedSint64Extension , 706L);
+ message.addExtension(packedFixed32Extension , 707);
+ message.addExtension(packedFixed64Extension , 708L);
+ message.addExtension(packedSfixed32Extension, 709);
+ message.addExtension(packedSfixed64Extension, 710L);
+ message.addExtension(packedFloatExtension , 711F);
+ message.addExtension(packedDoubleExtension , 712D);
+ message.addExtension(packedBoolExtension , false);
+ message.addExtension(packedEnumExtension, ForeignEnum.FOREIGN_BAZ);
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensions message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64Extension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64Extension));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtension ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtension));
+ assertEqualsExactType(601 , message.getExtension(packedInt32Extension , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64Extension , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32Extension , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64Extension , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32Extension , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64Extension , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32Extension , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64Extension , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32Extension, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64Extension, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtension , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtension , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtension , 0));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAR,
+ message.getExtension(packedEnumExtension, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32Extension , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64Extension , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32Extension , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64Extension , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32Extension , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64Extension , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32Extension , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64Extension , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32Extension, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64Extension, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtension , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtension , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtension , 1));
+ assertEqualsExactType(ForeignEnum.FOREIGN_BAZ,
+ message.getExtension(packedEnumExtension, 1));
+ }
+
+ // ===================================================================
+ // Lite extensions
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}.
+ */
+ public static void assertAllExtensionsSet(
+ TestAllExtensionsLiteOrBuilder message) {
+ Assert.assertTrue(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignMessageExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportMessageExtensionLite ));
+
+ Assert.assertTrue(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertTrue(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertTrue(message.getExtension(optionalForeignMessageExtensionLite).hasC());
+ Assert.assertTrue(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+
+ Assert.assertTrue(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(optionalCordExtensionLite));
+
+ assertEqualsExactType(101 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(102L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(103 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(104L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(105 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(106L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(107 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(108L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(109 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(110L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(111F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(112D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("115", message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(toBytes("116"), message.getExtension(optionalBytesExtensionLite));
+
+ assertEqualsExactType(117, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(118, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(119, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(120, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(126, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(127, message.getExtension(optionalLazyMessageExtensionLite).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(optionalNestedEnumExtensionLite));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("124", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("125", message.getExtension(optionalCordExtensionLite));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ assertEqualsExactType(301 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(302L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(303 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(304L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(305 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(306L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(307 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(308L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(309 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(310L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(311F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(312D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("315", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("316"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(317, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(318, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(319, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(320, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(327, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAZ,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAZ,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("324", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("325", message.getExtension(repeatedCordExtensionLite, 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertTrue(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertTrue(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertTrue(message.hasExtension(defaultCordExtensionLite));
+
+ assertEqualsExactType(401 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType(402L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType(403 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType(404L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(405 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType(406L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType(407 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType(408L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType(409 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(410L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType(411F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType(412D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("415", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("416"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("424", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("425", message.getExtension(defaultCordExtensionLite));
+
+ Assert.assertTrue(message.hasExtension(oneofBytesExtensionLite));
+
+ assertEqualsExactType(toBytes("604"), message.getExtension(oneofBytesExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are cleared, and that getting the extensions returns their
+ * default values.
+ */
+ public static void assertExtensionsClear(
+ TestAllExtensionsLiteOrBuilder message) {
+ // hasBlah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasExtension(optionalInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalGroupExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalNestedMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalImportMessageExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalPublicImportMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalLazyMessageExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(optionalForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(optionalStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(optionalCordExtensionLite));
+
+ // Optional fields without defaults are set to zero or something like it.
+ assertEqualsExactType(0 , message.getExtension(optionalInt32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalInt64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalUint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalUint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSint32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalSint64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalFixed32ExtensionLite ));
+ assertEqualsExactType(0L , message.getExtension(optionalFixed64ExtensionLite ));
+ assertEqualsExactType(0 , message.getExtension(optionalSfixed32ExtensionLite));
+ assertEqualsExactType(0L , message.getExtension(optionalSfixed64ExtensionLite));
+ assertEqualsExactType(0F , message.getExtension(optionalFloatExtensionLite ));
+ assertEqualsExactType(0D , message.getExtension(optionalDoubleExtensionLite ));
+ assertEqualsExactType(false, message.getExtension(optionalBoolExtensionLite ));
+ assertEqualsExactType("" , message.getExtension(optionalStringExtensionLite ));
+ assertEqualsExactType(ByteString.EMPTY, message.getExtension(optionalBytesExtensionLite));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(message.getExtension(optionalGroupExtensionLite ).hasA());
+ Assert.assertFalse(message.getExtension(optionalNestedMessageExtensionLite ).hasBb());
+ Assert.assertFalse(message.getExtension(optionalForeignMessageExtensionLite ).hasC());
+ Assert.assertFalse(message.getExtension(optionalImportMessageExtensionLite ).hasD());
+ Assert.assertFalse(message.getExtension(optionalPublicImportMessageExtensionLite).hasE());
+ Assert.assertFalse(message.getExtension(optionalLazyMessageExtensionLite ).hasBb());
+
+ assertEqualsExactType(0, message.getExtension(optionalGroupExtensionLite ).getA());
+ assertEqualsExactType(0, message.getExtension(optionalNestedMessageExtensionLite ).getBb());
+ assertEqualsExactType(0, message.getExtension(optionalForeignMessageExtensionLite).getC());
+ assertEqualsExactType(0, message.getExtension(optionalImportMessageExtensionLite ).getD());
+ assertEqualsExactType(0, message.getExtension(
+ optionalPublicImportMessageExtensionLite).getE());
+ assertEqualsExactType(0, message.getExtension(optionalLazyMessageExtensionLite ).getBb());
+
+ // Enums without defaults are set to the first value in the enum.
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(optionalNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(optionalForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(optionalImportEnumExtensionLite));
+
+ assertEqualsExactType("", message.getExtension(optionalStringPieceExtensionLite));
+ assertEqualsExactType("", message.getExtension(optionalCordExtensionLite));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(0, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(0, message.getExtensionCount(repeatedCordExtensionLite));
+
+ // hasBlah() should also be false for all default fields.
+ Assert.assertFalse(message.hasExtension(defaultInt32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultInt64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultUint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSint64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed32ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultFixed64ExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultSfixed32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultSfixed64ExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultFloatExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultDoubleExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBoolExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultStringExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultBytesExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultNestedEnumExtensionLite ));
+ Assert.assertFalse(message.hasExtension(defaultForeignEnumExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultImportEnumExtensionLite ));
+
+ Assert.assertFalse(message.hasExtension(defaultStringPieceExtensionLite));
+ Assert.assertFalse(message.hasExtension(defaultCordExtensionLite));
+
+ // Fields with defaults have their default values (duh).
+ assertEqualsExactType( 41 , message.getExtension(defaultInt32ExtensionLite ));
+ assertEqualsExactType( 42L , message.getExtension(defaultInt64ExtensionLite ));
+ assertEqualsExactType( 43 , message.getExtension(defaultUint32ExtensionLite ));
+ assertEqualsExactType( 44L , message.getExtension(defaultUint64ExtensionLite ));
+ assertEqualsExactType(-45 , message.getExtension(defaultSint32ExtensionLite ));
+ assertEqualsExactType( 46L , message.getExtension(defaultSint64ExtensionLite ));
+ assertEqualsExactType( 47 , message.getExtension(defaultFixed32ExtensionLite ));
+ assertEqualsExactType( 48L , message.getExtension(defaultFixed64ExtensionLite ));
+ assertEqualsExactType( 49 , message.getExtension(defaultSfixed32ExtensionLite));
+ assertEqualsExactType(-50L , message.getExtension(defaultSfixed64ExtensionLite));
+ assertEqualsExactType( 51.5F , message.getExtension(defaultFloatExtensionLite ));
+ assertEqualsExactType( 52e3D , message.getExtension(defaultDoubleExtensionLite ));
+ assertEqualsExactType(true , message.getExtension(defaultBoolExtensionLite ));
+ assertEqualsExactType("hello", message.getExtension(defaultStringExtensionLite ));
+ assertEqualsExactType(toBytes("world"), message.getExtension(defaultBytesExtensionLite));
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(defaultNestedEnumExtensionLite ));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(defaultForeignEnumExtensionLite));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(defaultImportEnumExtensionLite));
+
+ assertEqualsExactType("abc", message.getExtension(defaultStringPieceExtensionLite));
+ assertEqualsExactType("123", message.getExtension(defaultCordExtensionLite));
+
+ Assert.assertFalse(message.hasExtension(oneofUint32ExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofNestedMessageExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofStringExtensionLite));
+ Assert.assertFalse(message.hasExtension(oneofBytesExtensionLite));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all extensions of
+ * {@code message} are set to the values assigned by {@code setAllExtensions}
+ * followed by {@code modifyRepeatedExtensions}.
+ */
+ public static void assertRepeatedExtensionsModified(
+ TestAllExtensionsLiteOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedBytesExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedGroupExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignMessageExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedLazyMessageExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedNestedEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedForeignEnumExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedImportEnumExtensionLite ));
+
+ Assert.assertEquals(2, message.getExtensionCount(repeatedStringPieceExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(repeatedCordExtensionLite));
+
+ assertEqualsExactType(201 , message.getExtension(repeatedInt32ExtensionLite , 0));
+ assertEqualsExactType(202L , message.getExtension(repeatedInt64ExtensionLite , 0));
+ assertEqualsExactType(203 , message.getExtension(repeatedUint32ExtensionLite , 0));
+ assertEqualsExactType(204L , message.getExtension(repeatedUint64ExtensionLite , 0));
+ assertEqualsExactType(205 , message.getExtension(repeatedSint32ExtensionLite , 0));
+ assertEqualsExactType(206L , message.getExtension(repeatedSint64ExtensionLite , 0));
+ assertEqualsExactType(207 , message.getExtension(repeatedFixed32ExtensionLite , 0));
+ assertEqualsExactType(208L , message.getExtension(repeatedFixed64ExtensionLite , 0));
+ assertEqualsExactType(209 , message.getExtension(repeatedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(210L , message.getExtension(repeatedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(211F , message.getExtension(repeatedFloatExtensionLite , 0));
+ assertEqualsExactType(212D , message.getExtension(repeatedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 0));
+ assertEqualsExactType("215", message.getExtension(repeatedStringExtensionLite , 0));
+ assertEqualsExactType(toBytes("216"), message.getExtension(repeatedBytesExtensionLite, 0));
+
+ assertEqualsExactType(217, message.getExtension(repeatedGroupExtensionLite ,0).getA());
+ assertEqualsExactType(218, message.getExtension(repeatedNestedMessageExtensionLite ,0).getBb());
+ assertEqualsExactType(219, message.getExtension(repeatedForeignMessageExtensionLite,0).getC());
+ assertEqualsExactType(220, message.getExtension(repeatedImportMessageExtensionLite ,0).getD());
+ assertEqualsExactType(227, message.getExtension(repeatedLazyMessageExtensionLite ,0).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.BAR,
+ message.getExtension(repeatedNestedEnumExtensionLite, 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(repeatedForeignEnumExtensionLite, 0));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_BAR,
+ message.getExtension(repeatedImportEnumExtensionLite, 0));
+
+ assertEqualsExactType("224", message.getExtension(repeatedStringPieceExtensionLite, 0));
+ assertEqualsExactType("225", message.getExtension(repeatedCordExtensionLite, 0));
+
+ // Actually verify the second (modified) elements now.
+ assertEqualsExactType(501 , message.getExtension(repeatedInt32ExtensionLite , 1));
+ assertEqualsExactType(502L , message.getExtension(repeatedInt64ExtensionLite , 1));
+ assertEqualsExactType(503 , message.getExtension(repeatedUint32ExtensionLite , 1));
+ assertEqualsExactType(504L , message.getExtension(repeatedUint64ExtensionLite , 1));
+ assertEqualsExactType(505 , message.getExtension(repeatedSint32ExtensionLite , 1));
+ assertEqualsExactType(506L , message.getExtension(repeatedSint64ExtensionLite , 1));
+ assertEqualsExactType(507 , message.getExtension(repeatedFixed32ExtensionLite , 1));
+ assertEqualsExactType(508L , message.getExtension(repeatedFixed64ExtensionLite , 1));
+ assertEqualsExactType(509 , message.getExtension(repeatedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(510L , message.getExtension(repeatedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(511F , message.getExtension(repeatedFloatExtensionLite , 1));
+ assertEqualsExactType(512D , message.getExtension(repeatedDoubleExtensionLite , 1));
+ assertEqualsExactType(true , message.getExtension(repeatedBoolExtensionLite , 1));
+ assertEqualsExactType("515", message.getExtension(repeatedStringExtensionLite , 1));
+ assertEqualsExactType(toBytes("516"), message.getExtension(repeatedBytesExtensionLite, 1));
+
+ assertEqualsExactType(517, message.getExtension(repeatedGroupExtensionLite ,1).getA());
+ assertEqualsExactType(518, message.getExtension(repeatedNestedMessageExtensionLite ,1).getBb());
+ assertEqualsExactType(519, message.getExtension(repeatedForeignMessageExtensionLite,1).getC());
+ assertEqualsExactType(520, message.getExtension(repeatedImportMessageExtensionLite ,1).getD());
+ assertEqualsExactType(527, message.getExtension(repeatedLazyMessageExtensionLite ,1).getBb());
+
+ assertEqualsExactType(TestAllTypesLite.NestedEnum.FOO,
+ message.getExtension(repeatedNestedEnumExtensionLite, 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_FOO,
+ message.getExtension(repeatedForeignEnumExtensionLite, 1));
+ assertEqualsExactType(ImportEnumLite.IMPORT_LITE_FOO,
+ message.getExtension(repeatedImportEnumExtensionLite, 1));
+
+ assertEqualsExactType("524", message.getExtension(repeatedStringPieceExtensionLite, 1));
+ assertEqualsExactType("525", message.getExtension(repeatedCordExtensionLite, 1));
+ }
+
+ public static void assertPackedExtensionsSet(TestPackedExtensionsLite message) {
+ Assert.assertEquals(2, message.getExtensionCount(packedInt32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedInt64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedUint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSint64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed32ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedFixed64ExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed32ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedSfixed64ExtensionLite));
+ Assert.assertEquals(2, message.getExtensionCount(packedFloatExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedDoubleExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedBoolExtensionLite ));
+ Assert.assertEquals(2, message.getExtensionCount(packedEnumExtensionLite));
+ assertEqualsExactType(601 , message.getExtension(packedInt32ExtensionLite , 0));
+ assertEqualsExactType(602L , message.getExtension(packedInt64ExtensionLite , 0));
+ assertEqualsExactType(603 , message.getExtension(packedUint32ExtensionLite , 0));
+ assertEqualsExactType(604L , message.getExtension(packedUint64ExtensionLite , 0));
+ assertEqualsExactType(605 , message.getExtension(packedSint32ExtensionLite , 0));
+ assertEqualsExactType(606L , message.getExtension(packedSint64ExtensionLite , 0));
+ assertEqualsExactType(607 , message.getExtension(packedFixed32ExtensionLite , 0));
+ assertEqualsExactType(608L , message.getExtension(packedFixed64ExtensionLite , 0));
+ assertEqualsExactType(609 , message.getExtension(packedSfixed32ExtensionLite, 0));
+ assertEqualsExactType(610L , message.getExtension(packedSfixed64ExtensionLite, 0));
+ assertEqualsExactType(611F , message.getExtension(packedFloatExtensionLite , 0));
+ assertEqualsExactType(612D , message.getExtension(packedDoubleExtensionLite , 0));
+ assertEqualsExactType(true , message.getExtension(packedBoolExtensionLite , 0));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAR,
+ message.getExtension(packedEnumExtensionLite, 0));
+ assertEqualsExactType(701 , message.getExtension(packedInt32ExtensionLite , 1));
+ assertEqualsExactType(702L , message.getExtension(packedInt64ExtensionLite , 1));
+ assertEqualsExactType(703 , message.getExtension(packedUint32ExtensionLite , 1));
+ assertEqualsExactType(704L , message.getExtension(packedUint64ExtensionLite , 1));
+ assertEqualsExactType(705 , message.getExtension(packedSint32ExtensionLite , 1));
+ assertEqualsExactType(706L , message.getExtension(packedSint64ExtensionLite , 1));
+ assertEqualsExactType(707 , message.getExtension(packedFixed32ExtensionLite , 1));
+ assertEqualsExactType(708L , message.getExtension(packedFixed64ExtensionLite , 1));
+ assertEqualsExactType(709 , message.getExtension(packedSfixed32ExtensionLite, 1));
+ assertEqualsExactType(710L , message.getExtension(packedSfixed64ExtensionLite, 1));
+ assertEqualsExactType(711F , message.getExtension(packedFloatExtensionLite , 1));
+ assertEqualsExactType(712D , message.getExtension(packedDoubleExtensionLite , 1));
+ assertEqualsExactType(false, message.getExtension(packedBoolExtensionLite , 1));
+ assertEqualsExactType(ForeignEnumLite.FOREIGN_LITE_BAZ,
+ message.getExtension(packedEnumExtensionLite, 1));
+ }
+
+ // ===================================================================
+ // oneof
+ public static void setOneof(TestOneof2.Builder message) {
+ message.setFooLazyMessage(
+ TestOneof2.NestedMessage.newBuilder().setQuxInt(100).build());
+ message.setBarString("101");
+ message.setBazInt(102);
+ message.setBazString("103");
+ }
+
+ public static void assertOneofSet(TestOneof2 message) {
+ Assert.assertTrue(message.hasFooLazyMessage ());
+ Assert.assertTrue(message.getFooLazyMessage().hasQuxInt());
+
+ Assert.assertTrue(message.hasBarString());
+ Assert.assertTrue(message.hasBazInt ());
+ Assert.assertTrue(message.hasBazString());
+
+ Assert.assertEquals(100 , message.getFooLazyMessage().getQuxInt());
+ Assert.assertEquals("101", message.getBarString ());
+ Assert.assertEquals(102 , message.getBazInt ());
+ Assert.assertEquals("103", message.getBazString ());
+ }
+
+ public static void assertAtMostOneFieldSetOneof(TestOneof2 message) {
+ int count = 0;
+ if (message.hasFooInt()) { ++count; }
+ if (message.hasFooString()) { ++count; }
+ if (message.hasFooCord()) { ++count; }
+ if (message.hasFooStringPiece()) { ++count; }
+ if (message.hasFooBytes()) { ++count; }
+ if (message.hasFooEnum()) { ++count; }
+ if (message.hasFooMessage()) { ++count; }
+ if (message.hasFooGroup()) { ++count; }
+ if (message.hasFooLazyMessage()) { ++count; }
+ Assert.assertTrue(count <= 1);
+
+ count = 0;
+ if (message.hasBarInt()) { ++count; }
+ if (message.hasBarString()) { ++count; }
+ if (message.hasBarCord()) { ++count; }
+ if (message.hasBarStringPiece()) { ++count; }
+ if (message.hasBarBytes()) { ++count; }
+ if (message.hasBarEnum()) { ++count; }
+ Assert.assertTrue(count <= 1);
+
+ switch (message.getFooCase()) {
+ case FOO_INT:
+ Assert.assertTrue(message.hasFooInt());
+ break;
+ case FOO_STRING:
+ Assert.assertTrue(message.hasFooString());
+ break;
+ case FOO_CORD:
+ Assert.assertTrue(message.hasFooCord());
+ break;
+ case FOO_STRING_PIECE:
+ Assert.assertTrue(message.hasFooStringPiece());
+ break;
+ case FOO_BYTES:
+ Assert.assertTrue(message.hasFooBytes());
+ break;
+ case FOO_ENUM:
+ Assert.assertTrue(message.hasFooEnum());
+ break;
+ case FOO_MESSAGE:
+ Assert.assertTrue(message.hasFooMessage());
+ break;
+ case FOOGROUP:
+ Assert.assertTrue(message.hasFooGroup());
+ break;
+ case FOO_LAZY_MESSAGE:
+ Assert.assertTrue(message.hasFooLazyMessage());
+ break;
+ case FOO_NOT_SET:
+ break;
+ }
+ }
+
+ // =================================================================
+
+ /**
+ * Performs the same things that the methods of {@code TestUtil} do, but
+ * via the reflection interface. This is its own class because it needs
+ * to know what descriptor to use.
+ */
+ public static class ReflectionTester {
+ private final Descriptors.Descriptor baseDescriptor;
+ private final ExtensionRegistry extensionRegistry;
+
+ private final Descriptors.FileDescriptor file;
+ private final Descriptors.FileDescriptor importFile;
+ private final Descriptors.FileDescriptor publicImportFile;
+
+ private final Descriptors.Descriptor optionalGroup;
+ private final Descriptors.Descriptor repeatedGroup;
+ private final Descriptors.Descriptor nestedMessage;
+ private final Descriptors.Descriptor foreignMessage;
+ private final Descriptors.Descriptor importMessage;
+ private final Descriptors.Descriptor publicImportMessage;
+
+ private final Descriptors.FieldDescriptor groupA;
+ private final Descriptors.FieldDescriptor repeatedGroupA;
+ private final Descriptors.FieldDescriptor nestedB;
+ private final Descriptors.FieldDescriptor foreignC;
+ private final Descriptors.FieldDescriptor importD;
+ private final Descriptors.FieldDescriptor importE;
+
+ private final Descriptors.EnumDescriptor nestedEnum;
+ private final Descriptors.EnumDescriptor foreignEnum;
+ private final Descriptors.EnumDescriptor importEnum;
+
+ private final Descriptors.EnumValueDescriptor nestedFoo;
+ private final Descriptors.EnumValueDescriptor nestedBar;
+ private final Descriptors.EnumValueDescriptor nestedBaz;
+ private final Descriptors.EnumValueDescriptor foreignFoo;
+ private final Descriptors.EnumValueDescriptor foreignBar;
+ private final Descriptors.EnumValueDescriptor foreignBaz;
+ private final Descriptors.EnumValueDescriptor importFoo;
+ private final Descriptors.EnumValueDescriptor importBar;
+ private final Descriptors.EnumValueDescriptor importBaz;
+
+ /**
+ * Construct a {@code ReflectionTester} that will expect messages using
+ * the given descriptor.
+ *
+ * Normally {@code baseDescriptor} should be a descriptor for the type
+ * {@code TestAllTypes}, defined in
+ * {@code google/protobuf/unittest.proto}. However, if
+ * {@code extensionRegistry} is non-null, then {@code baseDescriptor} should
+ * be for {@code TestAllExtensions} instead, and instead of reading and
+ * writing normal fields, the tester will read and write extensions.
+ * All of {@code TestAllExtensions}' extensions must be registered in the
+ * registry.
+ */
+ public ReflectionTester(Descriptors.Descriptor baseDescriptor,
+ ExtensionRegistry extensionRegistry) {
+ this.baseDescriptor = baseDescriptor;
+ this.extensionRegistry = extensionRegistry;
+
+ this.file = baseDescriptor.getFile();
+ Assert.assertEquals(1, file.getDependencies().size());
+ this.importFile = file.getDependencies().get(0);
+ this.publicImportFile = importFile.getDependencies().get(0);
+
+ Descriptors.Descriptor testAllTypes;
+ if (baseDescriptor.getName() == "TestAllTypes") {
+ testAllTypes = baseDescriptor;
+ } else {
+ testAllTypes = file.findMessageTypeByName("TestAllTypes");
+ Assert.assertNotNull(testAllTypes);
+ }
+
+ if (extensionRegistry == null) {
+ // Use testAllTypes, rather than baseDescriptor, to allow
+ // initialization using TestPackedTypes descriptors. These objects
+ // won't be used by the methods for packed fields.
+ this.optionalGroup =
+ testAllTypes.findNestedTypeByName("OptionalGroup");
+ this.repeatedGroup =
+ testAllTypes.findNestedTypeByName("RepeatedGroup");
+ } else {
+ this.optionalGroup =
+ file.findMessageTypeByName("OptionalGroup_extension");
+ this.repeatedGroup =
+ file.findMessageTypeByName("RepeatedGroup_extension");
+ }
+ this.nestedMessage = testAllTypes.findNestedTypeByName("NestedMessage");
+ this.foreignMessage = file.findMessageTypeByName("ForeignMessage");
+ this.importMessage = importFile.findMessageTypeByName("ImportMessage");
+ this.publicImportMessage = publicImportFile.findMessageTypeByName(
+ "PublicImportMessage");
+
+ this.nestedEnum = testAllTypes.findEnumTypeByName("NestedEnum");
+ this.foreignEnum = file.findEnumTypeByName("ForeignEnum");
+ this.importEnum = importFile.findEnumTypeByName("ImportEnum");
+
+ Assert.assertNotNull(optionalGroup );
+ Assert.assertNotNull(repeatedGroup );
+ Assert.assertNotNull(nestedMessage );
+ Assert.assertNotNull(foreignMessage);
+ Assert.assertNotNull(importMessage );
+ Assert.assertNotNull(nestedEnum );
+ Assert.assertNotNull(foreignEnum );
+ Assert.assertNotNull(importEnum );
+
+ this.nestedB = nestedMessage .findFieldByName("bb");
+ this.foreignC = foreignMessage.findFieldByName("c");
+ this.importD = importMessage .findFieldByName("d");
+ this.importE = publicImportMessage.findFieldByName("e");
+ this.nestedFoo = nestedEnum.findValueByName("FOO");
+ this.nestedBar = nestedEnum.findValueByName("BAR");
+ this.nestedBaz = nestedEnum.findValueByName("BAZ");
+ this.foreignFoo = foreignEnum.findValueByName("FOREIGN_FOO");
+ this.foreignBar = foreignEnum.findValueByName("FOREIGN_BAR");
+ this.foreignBaz = foreignEnum.findValueByName("FOREIGN_BAZ");
+ this.importFoo = importEnum.findValueByName("IMPORT_FOO");
+ this.importBar = importEnum.findValueByName("IMPORT_BAR");
+ this.importBaz = importEnum.findValueByName("IMPORT_BAZ");
+
+ this.groupA = optionalGroup.findFieldByName("a");
+ this.repeatedGroupA = repeatedGroup.findFieldByName("a");
+
+ Assert.assertNotNull(groupA );
+ Assert.assertNotNull(repeatedGroupA);
+ Assert.assertNotNull(nestedB );
+ Assert.assertNotNull(foreignC );
+ Assert.assertNotNull(importD );
+ Assert.assertNotNull(importE );
+ Assert.assertNotNull(nestedFoo );
+ Assert.assertNotNull(nestedBar );
+ Assert.assertNotNull(nestedBaz );
+ Assert.assertNotNull(foreignFoo );
+ Assert.assertNotNull(foreignBar );
+ Assert.assertNotNull(foreignBaz );
+ Assert.assertNotNull(importFoo );
+ Assert.assertNotNull(importBar );
+ Assert.assertNotNull(importBaz );
+ }
+
+ /**
+ * Shorthand to get a FieldDescriptor for a field of unittest::TestAllTypes.
+ */
+ private Descriptors.FieldDescriptor f(String name) {
+ Descriptors.FieldDescriptor result;
+ if (extensionRegistry == null) {
+ result = baseDescriptor.findFieldByName(name);
+ } else {
+ result = file.findExtensionByName(name + "_extension");
+ }
+ Assert.assertNotNull(result);
+ return result;
+ }
+
+ /**
+ * Calls {@code parent.newBuilderForField()} or uses the
+ * {@code ExtensionRegistry} to find an appropriate builder, depending
+ * on what type is being tested.
+ */
+ private Message.Builder newBuilderForField(
+ Message.Builder parent, Descriptors.FieldDescriptor field) {
+ if (extensionRegistry == null) {
+ return parent.newBuilderForField(field);
+ } else {
+ ExtensionRegistry.ExtensionInfo extension =
+ extensionRegistry.findImmutableExtensionByNumber(
+ field.getContainingType(), field.getNumber());
+ Assert.assertNotNull(extension);
+ Assert.assertNotNull(extension.defaultInstance);
+ return extension.defaultInstance.newBuilderForType();
+ }
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllFieldsSet()}, using the {@link Message.Builder}
+ * reflection interface.
+ */
+ void setAllFieldsViaReflection(Message.Builder message) {
+ message.setField(f("optional_int32" ), 101 );
+ message.setField(f("optional_int64" ), 102L);
+ message.setField(f("optional_uint32" ), 103 );
+ message.setField(f("optional_uint64" ), 104L);
+ message.setField(f("optional_sint32" ), 105 );
+ message.setField(f("optional_sint64" ), 106L);
+ message.setField(f("optional_fixed32" ), 107 );
+ message.setField(f("optional_fixed64" ), 108L);
+ message.setField(f("optional_sfixed32"), 109 );
+ message.setField(f("optional_sfixed64"), 110L);
+ message.setField(f("optional_float" ), 111F);
+ message.setField(f("optional_double" ), 112D);
+ message.setField(f("optional_bool" ), true);
+ message.setField(f("optional_string" ), "115");
+ message.setField(f("optional_bytes" ), toBytes("116"));
+
+ message.setField(f("optionalgroup"),
+ newBuilderForField(message, f("optionalgroup"))
+ .setField(groupA, 117).build());
+ message.setField(f("optional_nested_message"),
+ newBuilderForField(message, f("optional_nested_message"))
+ .setField(nestedB, 118).build());
+ message.setField(f("optional_foreign_message"),
+ newBuilderForField(message, f("optional_foreign_message"))
+ .setField(foreignC, 119).build());
+ message.setField(f("optional_import_message"),
+ newBuilderForField(message, f("optional_import_message"))
+ .setField(importD, 120).build());
+ message.setField(f("optional_public_import_message"),
+ newBuilderForField(message, f("optional_public_import_message"))
+ .setField(importE, 126).build());
+ message.setField(f("optional_lazy_message"),
+ newBuilderForField(message, f("optional_lazy_message"))
+ .setField(nestedB, 127).build());
+
+ message.setField(f("optional_nested_enum" ), nestedBaz);
+ message.setField(f("optional_foreign_enum"), foreignBaz);
+ message.setField(f("optional_import_enum" ), importBaz);
+
+ message.setField(f("optional_string_piece" ), "124");
+ message.setField(f("optional_cord" ), "125");
+
+ // -----------------------------------------------------------------
+
+ message.addRepeatedField(f("repeated_int32" ), 201 );
+ message.addRepeatedField(f("repeated_int64" ), 202L);
+ message.addRepeatedField(f("repeated_uint32" ), 203 );
+ message.addRepeatedField(f("repeated_uint64" ), 204L);
+ message.addRepeatedField(f("repeated_sint32" ), 205 );
+ message.addRepeatedField(f("repeated_sint64" ), 206L);
+ message.addRepeatedField(f("repeated_fixed32" ), 207 );
+ message.addRepeatedField(f("repeated_fixed64" ), 208L);
+ message.addRepeatedField(f("repeated_sfixed32"), 209 );
+ message.addRepeatedField(f("repeated_sfixed64"), 210L);
+ message.addRepeatedField(f("repeated_float" ), 211F);
+ message.addRepeatedField(f("repeated_double" ), 212D);
+ message.addRepeatedField(f("repeated_bool" ), true);
+ message.addRepeatedField(f("repeated_string" ), "215");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("216"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 217).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 218).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 219).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 220).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 227).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBar);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBar);
+ message.addRepeatedField(f("repeated_import_enum" ), importBar);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "224");
+ message.addRepeatedField(f("repeated_cord" ), "225");
+
+ // Add a second one of each field.
+ message.addRepeatedField(f("repeated_int32" ), 301 );
+ message.addRepeatedField(f("repeated_int64" ), 302L);
+ message.addRepeatedField(f("repeated_uint32" ), 303 );
+ message.addRepeatedField(f("repeated_uint64" ), 304L);
+ message.addRepeatedField(f("repeated_sint32" ), 305 );
+ message.addRepeatedField(f("repeated_sint64" ), 306L);
+ message.addRepeatedField(f("repeated_fixed32" ), 307 );
+ message.addRepeatedField(f("repeated_fixed64" ), 308L);
+ message.addRepeatedField(f("repeated_sfixed32"), 309 );
+ message.addRepeatedField(f("repeated_sfixed64"), 310L);
+ message.addRepeatedField(f("repeated_float" ), 311F);
+ message.addRepeatedField(f("repeated_double" ), 312D);
+ message.addRepeatedField(f("repeated_bool" ), false);
+ message.addRepeatedField(f("repeated_string" ), "315");
+ message.addRepeatedField(f("repeated_bytes" ), toBytes("316"));
+
+ message.addRepeatedField(f("repeatedgroup"),
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 317).build());
+ message.addRepeatedField(f("repeated_nested_message"),
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 318).build());
+ message.addRepeatedField(f("repeated_foreign_message"),
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 319).build());
+ message.addRepeatedField(f("repeated_import_message"),
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 320).build());
+ message.addRepeatedField(f("repeated_lazy_message"),
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 327).build());
+
+ message.addRepeatedField(f("repeated_nested_enum" ), nestedBaz);
+ message.addRepeatedField(f("repeated_foreign_enum"), foreignBaz);
+ message.addRepeatedField(f("repeated_import_enum" ), importBaz);
+
+ message.addRepeatedField(f("repeated_string_piece" ), "324");
+ message.addRepeatedField(f("repeated_cord" ), "325");
+
+ // -----------------------------------------------------------------
+
+ message.setField(f("default_int32" ), 401 );
+ message.setField(f("default_int64" ), 402L);
+ message.setField(f("default_uint32" ), 403 );
+ message.setField(f("default_uint64" ), 404L);
+ message.setField(f("default_sint32" ), 405 );
+ message.setField(f("default_sint64" ), 406L);
+ message.setField(f("default_fixed32" ), 407 );
+ message.setField(f("default_fixed64" ), 408L);
+ message.setField(f("default_sfixed32"), 409 );
+ message.setField(f("default_sfixed64"), 410L);
+ message.setField(f("default_float" ), 411F);
+ message.setField(f("default_double" ), 412D);
+ message.setField(f("default_bool" ), false);
+ message.setField(f("default_string" ), "415");
+ message.setField(f("default_bytes" ), toBytes("416"));
+
+ message.setField(f("default_nested_enum" ), nestedFoo);
+ message.setField(f("default_foreign_enum"), foreignFoo);
+ message.setField(f("default_import_enum" ), importFoo);
+
+ message.setField(f("default_string_piece" ), "424");
+ message.setField(f("default_cord" ), "425");
+
+ message.setField(f("oneof_uint32" ), 601);
+ message.setField(f("oneof_nested_message"),
+ newBuilderForField(message, f("oneof_nested_message"))
+ .setField(nestedB, 602).build());
+ message.setField(f("oneof_string" ), "603");
+ message.setField(f("oneof_bytes" ), toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated fields of {@code message} to contain the values
+ * expected by {@code assertRepeatedFieldsModified()}, using the
+ * {@link Message.Builder} reflection interface.
+ */
+ void modifyRepeatedFieldsViaReflection(Message.Builder message) {
+ message.setRepeatedField(f("repeated_int32" ), 1, 501 );
+ message.setRepeatedField(f("repeated_int64" ), 1, 502L);
+ message.setRepeatedField(f("repeated_uint32" ), 1, 503 );
+ message.setRepeatedField(f("repeated_uint64" ), 1, 504L);
+ message.setRepeatedField(f("repeated_sint32" ), 1, 505 );
+ message.setRepeatedField(f("repeated_sint64" ), 1, 506L);
+ message.setRepeatedField(f("repeated_fixed32" ), 1, 507 );
+ message.setRepeatedField(f("repeated_fixed64" ), 1, 508L);
+ message.setRepeatedField(f("repeated_sfixed32"), 1, 509 );
+ message.setRepeatedField(f("repeated_sfixed64"), 1, 510L);
+ message.setRepeatedField(f("repeated_float" ), 1, 511F);
+ message.setRepeatedField(f("repeated_double" ), 1, 512D);
+ message.setRepeatedField(f("repeated_bool" ), 1, true);
+ message.setRepeatedField(f("repeated_string" ), 1, "515");
+ message.setRepeatedField(f("repeated_bytes" ), 1, toBytes("516"));
+
+ message.setRepeatedField(f("repeatedgroup"), 1,
+ newBuilderForField(message, f("repeatedgroup"))
+ .setField(repeatedGroupA, 517).build());
+ message.setRepeatedField(f("repeated_nested_message"), 1,
+ newBuilderForField(message, f("repeated_nested_message"))
+ .setField(nestedB, 518).build());
+ message.setRepeatedField(f("repeated_foreign_message"), 1,
+ newBuilderForField(message, f("repeated_foreign_message"))
+ .setField(foreignC, 519).build());
+ message.setRepeatedField(f("repeated_import_message"), 1,
+ newBuilderForField(message, f("repeated_import_message"))
+ .setField(importD, 520).build());
+ message.setRepeatedField(f("repeated_lazy_message"), 1,
+ newBuilderForField(message, f("repeated_lazy_message"))
+ .setField(nestedB, 527).build());
+
+ message.setRepeatedField(f("repeated_nested_enum" ), 1, nestedFoo);
+ message.setRepeatedField(f("repeated_foreign_enum"), 1, foreignFoo);
+ message.setRepeatedField(f("repeated_import_enum" ), 1, importFoo);
+
+ message.setRepeatedField(f("repeated_string_piece"), 1, "524");
+ message.setRepeatedField(f("repeated_cord"), 1, "525");
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are set to the values assigned by {@code setAllFields},
+ * using the {@link Message} reflection interface.
+ */
+ public void assertAllFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertTrue(message.hasField(f("optional_int32" )));
+ Assert.assertTrue(message.hasField(f("optional_int64" )));
+ Assert.assertTrue(message.hasField(f("optional_uint32" )));
+ Assert.assertTrue(message.hasField(f("optional_uint64" )));
+ Assert.assertTrue(message.hasField(f("optional_sint32" )));
+ Assert.assertTrue(message.hasField(f("optional_sint64" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed32" )));
+ Assert.assertTrue(message.hasField(f("optional_fixed64" )));
+ Assert.assertTrue(message.hasField(f("optional_sfixed32")));
+ Assert.assertTrue(message.hasField(f("optional_sfixed64")));
+ Assert.assertTrue(message.hasField(f("optional_float" )));
+ Assert.assertTrue(message.hasField(f("optional_double" )));
+ Assert.assertTrue(message.hasField(f("optional_bool" )));
+ Assert.assertTrue(message.hasField(f("optional_string" )));
+ Assert.assertTrue(message.hasField(f("optional_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("optionalgroup" )));
+ Assert.assertTrue(message.hasField(f("optional_nested_message" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_message")));
+ Assert.assertTrue(message.hasField(f("optional_import_message" )));
+
+ Assert.assertTrue(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertTrue(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+
+ Assert.assertTrue(message.hasField(f("optional_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("optional_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("optional_string_piece")));
+ Assert.assertTrue(message.hasField(f("optional_cord")));
+
+ Assert.assertEquals(101 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(102L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(103 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(104L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(105 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(106L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(107 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(108L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(109 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(110L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(111F , message.getField(f("optional_float" )));
+ Assert.assertEquals(112D , message.getField(f("optional_double" )));
+ Assert.assertEquals(true , message.getField(f("optional_bool" )));
+ Assert.assertEquals("115", message.getField(f("optional_string" )));
+ Assert.assertEquals(toBytes("116"), message.getField(f("optional_bytes")));
+
+ Assert.assertEquals(117,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(118,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(119,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(120,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(126,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(127,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignBaz, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importBaz, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("124", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("125", message.getField(f("optional_cord")));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(301 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(302L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(303 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(304L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(305 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(306L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(307 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(308L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(309 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(310L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(311F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(312D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("315", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("316"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(317,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(318,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(319,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(320,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(327,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBaz, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importBaz, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("324", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("325", message.getRepeatedField(f("repeated_cord"), 1));
+
+ // -----------------------------------------------------------------
+
+ Assert.assertTrue(message.hasField(f("default_int32" )));
+ Assert.assertTrue(message.hasField(f("default_int64" )));
+ Assert.assertTrue(message.hasField(f("default_uint32" )));
+ Assert.assertTrue(message.hasField(f("default_uint64" )));
+ Assert.assertTrue(message.hasField(f("default_sint32" )));
+ Assert.assertTrue(message.hasField(f("default_sint64" )));
+ Assert.assertTrue(message.hasField(f("default_fixed32" )));
+ Assert.assertTrue(message.hasField(f("default_fixed64" )));
+ Assert.assertTrue(message.hasField(f("default_sfixed32")));
+ Assert.assertTrue(message.hasField(f("default_sfixed64")));
+ Assert.assertTrue(message.hasField(f("default_float" )));
+ Assert.assertTrue(message.hasField(f("default_double" )));
+ Assert.assertTrue(message.hasField(f("default_bool" )));
+ Assert.assertTrue(message.hasField(f("default_string" )));
+ Assert.assertTrue(message.hasField(f("default_bytes" )));
+
+ Assert.assertTrue(message.hasField(f("default_nested_enum" )));
+ Assert.assertTrue(message.hasField(f("default_foreign_enum")));
+ Assert.assertTrue(message.hasField(f("default_import_enum" )));
+
+ Assert.assertTrue(message.hasField(f("default_string_piece")));
+ Assert.assertTrue(message.hasField(f("default_cord")));
+
+ Assert.assertEquals(401 , message.getField(f("default_int32" )));
+ Assert.assertEquals(402L , message.getField(f("default_int64" )));
+ Assert.assertEquals(403 , message.getField(f("default_uint32" )));
+ Assert.assertEquals(404L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(405 , message.getField(f("default_sint32" )));
+ Assert.assertEquals(406L , message.getField(f("default_sint64" )));
+ Assert.assertEquals(407 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals(408L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals(409 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(410L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals(411F , message.getField(f("default_float" )));
+ Assert.assertEquals(412D , message.getField(f("default_double" )));
+ Assert.assertEquals(false, message.getField(f("default_bool" )));
+ Assert.assertEquals("415", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("416"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedFoo, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("424", message.getField(f("default_string_piece")));
+ Assert.assertEquals("425", message.getField(f("default_cord")));
+
+ Assert.assertTrue(message.hasField(f("oneof_bytes")));
+ Assert.assertEquals(toBytes("604"), message.getField(f("oneof_bytes")));
+
+ if (extensionRegistry == null) {
+ Assert.assertFalse(message.hasField(f("oneof_uint32")));
+ Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+ Assert.assertFalse(message.hasField(f("oneof_string")));
+ } else {
+ Assert.assertTrue(message.hasField(f("oneof_uint32")));
+ Assert.assertTrue(message.hasField(f("oneof_nested_message")));
+ Assert.assertTrue(message.hasField(f("oneof_string")));
+ Assert.assertEquals(601, message.getField(f("oneof_uint32")));
+ Assert.assertEquals(602,
+ ((MessageOrBuilder) message.getField(f("oneof_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals("603", message.getField(f("oneof_string")));
+ }
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Assert (using {@code junit.framework.Assert}} that all fields of
+ * {@code message} are cleared, and that getting the fields returns their
+ * default values, using the {@link Message} reflection interface.
+ */
+ public void assertClearViaReflection(MessageOrBuilder message) {
+ // has_blah() should initially be false for all optional fields.
+ Assert.assertFalse(message.hasField(f("optional_int32" )));
+ Assert.assertFalse(message.hasField(f("optional_int64" )));
+ Assert.assertFalse(message.hasField(f("optional_uint32" )));
+ Assert.assertFalse(message.hasField(f("optional_uint64" )));
+ Assert.assertFalse(message.hasField(f("optional_sint32" )));
+ Assert.assertFalse(message.hasField(f("optional_sint64" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed32" )));
+ Assert.assertFalse(message.hasField(f("optional_fixed64" )));
+ Assert.assertFalse(message.hasField(f("optional_sfixed32")));
+ Assert.assertFalse(message.hasField(f("optional_sfixed64")));
+ Assert.assertFalse(message.hasField(f("optional_float" )));
+ Assert.assertFalse(message.hasField(f("optional_double" )));
+ Assert.assertFalse(message.hasField(f("optional_bool" )));
+ Assert.assertFalse(message.hasField(f("optional_string" )));
+ Assert.assertFalse(message.hasField(f("optional_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("optionalgroup" )));
+ Assert.assertFalse(message.hasField(f("optional_nested_message" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_message")));
+ Assert.assertFalse(message.hasField(f("optional_import_message" )));
+
+ Assert.assertFalse(message.hasField(f("optional_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("optional_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("optional_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("optional_string_piece")));
+ Assert.assertFalse(message.hasField(f("optional_cord")));
+
+ // Optional fields without defaults are set to zero or something like it.
+ Assert.assertEquals(0 , message.getField(f("optional_int32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_int64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_uint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_uint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sint32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_sint64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_fixed32" )));
+ Assert.assertEquals(0L , message.getField(f("optional_fixed64" )));
+ Assert.assertEquals(0 , message.getField(f("optional_sfixed32")));
+ Assert.assertEquals(0L , message.getField(f("optional_sfixed64")));
+ Assert.assertEquals(0F , message.getField(f("optional_float" )));
+ Assert.assertEquals(0D , message.getField(f("optional_double" )));
+ Assert.assertEquals(false, message.getField(f("optional_bool" )));
+ Assert.assertEquals("" , message.getField(f("optional_string" )));
+ Assert.assertEquals(ByteString.EMPTY, message.getField(f("optional_bytes")));
+
+ // Embedded messages should also be clear.
+ Assert.assertFalse(
+ ((Message)message.getField(f("optionalgroup"))).hasField(groupA));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_nested_message")))
+ .hasField(nestedB));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_foreign_message")))
+ .hasField(foreignC));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_import_message")))
+ .hasField(importD));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_public_import_message")))
+ .hasField(importE));
+ Assert.assertFalse(
+ ((Message)message.getField(f("optional_lazy_message")))
+ .hasField(nestedB));
+
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optionalgroup"))).getField(groupA));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_nested_message")))
+ .getField(nestedB));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_foreign_message")))
+ .getField(foreignC));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_import_message")))
+ .getField(importD));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_public_import_message")))
+ .getField(importE));
+ Assert.assertEquals(0,
+ ((Message)message.getField(f("optional_lazy_message")))
+ .getField(nestedB));
+
+ // Enums without defaults are set to the first value in the enum.
+ Assert.assertEquals( nestedFoo, message.getField(f("optional_nested_enum" )));
+ Assert.assertEquals(foreignFoo, message.getField(f("optional_foreign_enum")));
+ Assert.assertEquals( importFoo, message.getField(f("optional_import_enum" )));
+
+ Assert.assertEquals("", message.getField(f("optional_string_piece")));
+ Assert.assertEquals("", message.getField(f("optional_cord")));
+
+ // Repeated fields are empty.
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(0, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ // has_blah() should also be false for all default fields.
+ Assert.assertFalse(message.hasField(f("default_int32" )));
+ Assert.assertFalse(message.hasField(f("default_int64" )));
+ Assert.assertFalse(message.hasField(f("default_uint32" )));
+ Assert.assertFalse(message.hasField(f("default_uint64" )));
+ Assert.assertFalse(message.hasField(f("default_sint32" )));
+ Assert.assertFalse(message.hasField(f("default_sint64" )));
+ Assert.assertFalse(message.hasField(f("default_fixed32" )));
+ Assert.assertFalse(message.hasField(f("default_fixed64" )));
+ Assert.assertFalse(message.hasField(f("default_sfixed32")));
+ Assert.assertFalse(message.hasField(f("default_sfixed64")));
+ Assert.assertFalse(message.hasField(f("default_float" )));
+ Assert.assertFalse(message.hasField(f("default_double" )));
+ Assert.assertFalse(message.hasField(f("default_bool" )));
+ Assert.assertFalse(message.hasField(f("default_string" )));
+ Assert.assertFalse(message.hasField(f("default_bytes" )));
+
+ Assert.assertFalse(message.hasField(f("default_nested_enum" )));
+ Assert.assertFalse(message.hasField(f("default_foreign_enum")));
+ Assert.assertFalse(message.hasField(f("default_import_enum" )));
+
+ Assert.assertFalse(message.hasField(f("default_string_piece" )));
+ Assert.assertFalse(message.hasField(f("default_cord" )));
+
+ // Fields with defaults have their default values (duh).
+ Assert.assertEquals( 41 , message.getField(f("default_int32" )));
+ Assert.assertEquals( 42L , message.getField(f("default_int64" )));
+ Assert.assertEquals( 43 , message.getField(f("default_uint32" )));
+ Assert.assertEquals( 44L , message.getField(f("default_uint64" )));
+ Assert.assertEquals(-45 , message.getField(f("default_sint32" )));
+ Assert.assertEquals( 46L , message.getField(f("default_sint64" )));
+ Assert.assertEquals( 47 , message.getField(f("default_fixed32" )));
+ Assert.assertEquals( 48L , message.getField(f("default_fixed64" )));
+ Assert.assertEquals( 49 , message.getField(f("default_sfixed32")));
+ Assert.assertEquals(-50L , message.getField(f("default_sfixed64")));
+ Assert.assertEquals( 51.5F , message.getField(f("default_float" )));
+ Assert.assertEquals( 52e3D , message.getField(f("default_double" )));
+ Assert.assertEquals(true , message.getField(f("default_bool" )));
+ Assert.assertEquals("hello", message.getField(f("default_string" )));
+ Assert.assertEquals(toBytes("world"), message.getField(f("default_bytes")));
+
+ Assert.assertEquals( nestedBar, message.getField(f("default_nested_enum" )));
+ Assert.assertEquals(foreignBar, message.getField(f("default_foreign_enum")));
+ Assert.assertEquals( importBar, message.getField(f("default_import_enum" )));
+
+ Assert.assertEquals("abc", message.getField(f("default_string_piece")));
+ Assert.assertEquals("123", message.getField(f("default_cord")));
+
+ Assert.assertFalse(message.hasField(f("oneof_uint32")));
+ Assert.assertFalse(message.hasField(f("oneof_nested_message")));
+ Assert.assertFalse(message.hasField(f("oneof_string")));
+ Assert.assertFalse(message.hasField(f("oneof_bytes")));
+
+ Assert.assertEquals(0, message.getField(f("oneof_uint32")));
+ Assert.assertEquals("", message.getField(f("oneof_string")));
+ Assert.assertEquals(toBytes(""), message.getField(f("oneof_bytes")));
+ }
+
+
+ // ---------------------------------------------------------------
+
+ public void assertRepeatedFieldsModifiedViaReflection(
+ MessageOrBuilder message) {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_bytes" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeatedgroup" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_message")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_lazy_message" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_nested_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_foreign_enum" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_import_enum" )));
+
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_string_piece")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("repeated_cord")));
+
+ Assert.assertEquals(201 , message.getRepeatedField(f("repeated_int32" ), 0));
+ Assert.assertEquals(202L , message.getRepeatedField(f("repeated_int64" ), 0));
+ Assert.assertEquals(203 , message.getRepeatedField(f("repeated_uint32" ), 0));
+ Assert.assertEquals(204L , message.getRepeatedField(f("repeated_uint64" ), 0));
+ Assert.assertEquals(205 , message.getRepeatedField(f("repeated_sint32" ), 0));
+ Assert.assertEquals(206L , message.getRepeatedField(f("repeated_sint64" ), 0));
+ Assert.assertEquals(207 , message.getRepeatedField(f("repeated_fixed32" ), 0));
+ Assert.assertEquals(208L , message.getRepeatedField(f("repeated_fixed64" ), 0));
+ Assert.assertEquals(209 , message.getRepeatedField(f("repeated_sfixed32"), 0));
+ Assert.assertEquals(210L , message.getRepeatedField(f("repeated_sfixed64"), 0));
+ Assert.assertEquals(211F , message.getRepeatedField(f("repeated_float" ), 0));
+ Assert.assertEquals(212D , message.getRepeatedField(f("repeated_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 0));
+ Assert.assertEquals("215", message.getRepeatedField(f("repeated_string" ), 0));
+ Assert.assertEquals(toBytes("216"), message.getRepeatedField(f("repeated_bytes"), 0));
+
+ Assert.assertEquals(217,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 0))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(218,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 0))
+ .getField(nestedB));
+ Assert.assertEquals(219,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 0))
+ .getField(foreignC));
+ Assert.assertEquals(220,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 0))
+ .getField(importD));
+ Assert.assertEquals(227,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 0))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedBar, message.getRepeatedField(f("repeated_nested_enum" ),0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("repeated_foreign_enum"),0));
+ Assert.assertEquals( importBar, message.getRepeatedField(f("repeated_import_enum" ),0));
+
+ Assert.assertEquals("224", message.getRepeatedField(f("repeated_string_piece"), 0));
+ Assert.assertEquals("225", message.getRepeatedField(f("repeated_cord"), 0));
+
+ Assert.assertEquals(501 , message.getRepeatedField(f("repeated_int32" ), 1));
+ Assert.assertEquals(502L , message.getRepeatedField(f("repeated_int64" ), 1));
+ Assert.assertEquals(503 , message.getRepeatedField(f("repeated_uint32" ), 1));
+ Assert.assertEquals(504L , message.getRepeatedField(f("repeated_uint64" ), 1));
+ Assert.assertEquals(505 , message.getRepeatedField(f("repeated_sint32" ), 1));
+ Assert.assertEquals(506L , message.getRepeatedField(f("repeated_sint64" ), 1));
+ Assert.assertEquals(507 , message.getRepeatedField(f("repeated_fixed32" ), 1));
+ Assert.assertEquals(508L , message.getRepeatedField(f("repeated_fixed64" ), 1));
+ Assert.assertEquals(509 , message.getRepeatedField(f("repeated_sfixed32"), 1));
+ Assert.assertEquals(510L , message.getRepeatedField(f("repeated_sfixed64"), 1));
+ Assert.assertEquals(511F , message.getRepeatedField(f("repeated_float" ), 1));
+ Assert.assertEquals(512D , message.getRepeatedField(f("repeated_double" ), 1));
+ Assert.assertEquals(true , message.getRepeatedField(f("repeated_bool" ), 1));
+ Assert.assertEquals("515", message.getRepeatedField(f("repeated_string" ), 1));
+ Assert.assertEquals(toBytes("516"), message.getRepeatedField(f("repeated_bytes"), 1));
+
+ Assert.assertEquals(517,
+ ((Message)message.getRepeatedField(f("repeatedgroup"), 1))
+ .getField(repeatedGroupA));
+ Assert.assertEquals(518,
+ ((Message)message.getRepeatedField(f("repeated_nested_message"), 1))
+ .getField(nestedB));
+ Assert.assertEquals(519,
+ ((Message)message.getRepeatedField(f("repeated_foreign_message"), 1))
+ .getField(foreignC));
+ Assert.assertEquals(520,
+ ((Message)message.getRepeatedField(f("repeated_import_message"), 1))
+ .getField(importD));
+ Assert.assertEquals(527,
+ ((Message)message.getRepeatedField(f("repeated_lazy_message"), 1))
+ .getField(nestedB));
+
+ Assert.assertEquals( nestedFoo, message.getRepeatedField(f("repeated_nested_enum" ),1));
+ Assert.assertEquals(foreignFoo, message.getRepeatedField(f("repeated_foreign_enum"),1));
+ Assert.assertEquals( importFoo, message.getRepeatedField(f("repeated_import_enum" ),1));
+
+ Assert.assertEquals("524", message.getRepeatedField(f("repeated_string_piece"), 1));
+ Assert.assertEquals("525", message.getRepeatedField(f("repeated_cord"), 1));
+ }
+
+ public void setPackedFieldsViaReflection(Message.Builder message) {
+ message.addRepeatedField(f("packed_int32" ), 601 );
+ message.addRepeatedField(f("packed_int64" ), 602L);
+ message.addRepeatedField(f("packed_uint32" ), 603 );
+ message.addRepeatedField(f("packed_uint64" ), 604L);
+ message.addRepeatedField(f("packed_sint32" ), 605 );
+ message.addRepeatedField(f("packed_sint64" ), 606L);
+ message.addRepeatedField(f("packed_fixed32" ), 607 );
+ message.addRepeatedField(f("packed_fixed64" ), 608L);
+ message.addRepeatedField(f("packed_sfixed32"), 609 );
+ message.addRepeatedField(f("packed_sfixed64"), 610L);
+ message.addRepeatedField(f("packed_float" ), 611F);
+ message.addRepeatedField(f("packed_double" ), 612D);
+ message.addRepeatedField(f("packed_bool" ), true);
+ message.addRepeatedField(f("packed_enum" ), foreignBar);
+ // Add a second one of each field.
+ message.addRepeatedField(f("packed_int32" ), 701 );
+ message.addRepeatedField(f("packed_int64" ), 702L);
+ message.addRepeatedField(f("packed_uint32" ), 703 );
+ message.addRepeatedField(f("packed_uint64" ), 704L);
+ message.addRepeatedField(f("packed_sint32" ), 705 );
+ message.addRepeatedField(f("packed_sint64" ), 706L);
+ message.addRepeatedField(f("packed_fixed32" ), 707 );
+ message.addRepeatedField(f("packed_fixed64" ), 708L);
+ message.addRepeatedField(f("packed_sfixed32"), 709 );
+ message.addRepeatedField(f("packed_sfixed64"), 710L);
+ message.addRepeatedField(f("packed_float" ), 711F);
+ message.addRepeatedField(f("packed_double" ), 712D);
+ message.addRepeatedField(f("packed_bool" ), false);
+ message.addRepeatedField(f("packed_enum" ), foreignBaz);
+ }
+
+ public void assertPackedFieldsSetViaReflection(MessageOrBuilder message) {
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_int64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_uint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sint64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed32" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_fixed64" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed32")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_sfixed64")));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_float" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_double" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_bool" )));
+ Assert.assertEquals(2, message.getRepeatedFieldCount(f("packed_enum" )));
+ Assert.assertEquals(601 , message.getRepeatedField(f("packed_int32" ), 0));
+ Assert.assertEquals(602L , message.getRepeatedField(f("packed_int64" ), 0));
+ Assert.assertEquals(603 , message.getRepeatedField(f("packed_uint32" ), 0));
+ Assert.assertEquals(604L , message.getRepeatedField(f("packed_uint64" ), 0));
+ Assert.assertEquals(605 , message.getRepeatedField(f("packed_sint32" ), 0));
+ Assert.assertEquals(606L , message.getRepeatedField(f("packed_sint64" ), 0));
+ Assert.assertEquals(607 , message.getRepeatedField(f("packed_fixed32" ), 0));
+ Assert.assertEquals(608L , message.getRepeatedField(f("packed_fixed64" ), 0));
+ Assert.assertEquals(609 , message.getRepeatedField(f("packed_sfixed32"), 0));
+ Assert.assertEquals(610L , message.getRepeatedField(f("packed_sfixed64"), 0));
+ Assert.assertEquals(611F , message.getRepeatedField(f("packed_float" ), 0));
+ Assert.assertEquals(612D , message.getRepeatedField(f("packed_double" ), 0));
+ Assert.assertEquals(true , message.getRepeatedField(f("packed_bool" ), 0));
+ Assert.assertEquals(foreignBar, message.getRepeatedField(f("packed_enum" ),0));
+ Assert.assertEquals(701 , message.getRepeatedField(f("packed_int32" ), 1));
+ Assert.assertEquals(702L , message.getRepeatedField(f("packed_int64" ), 1));
+ Assert.assertEquals(703 , message.getRepeatedField(f("packed_uint32" ), 1));
+ Assert.assertEquals(704L , message.getRepeatedField(f("packed_uint64" ), 1));
+ Assert.assertEquals(705 , message.getRepeatedField(f("packed_sint32" ), 1));
+ Assert.assertEquals(706L , message.getRepeatedField(f("packed_sint64" ), 1));
+ Assert.assertEquals(707 , message.getRepeatedField(f("packed_fixed32" ), 1));
+ Assert.assertEquals(708L , message.getRepeatedField(f("packed_fixed64" ), 1));
+ Assert.assertEquals(709 , message.getRepeatedField(f("packed_sfixed32"), 1));
+ Assert.assertEquals(710L , message.getRepeatedField(f("packed_sfixed64"), 1));
+ Assert.assertEquals(711F , message.getRepeatedField(f("packed_float" ), 1));
+ Assert.assertEquals(712D , message.getRepeatedField(f("packed_double" ), 1));
+ Assert.assertEquals(false, message.getRepeatedField(f("packed_bool" ), 1));
+ Assert.assertEquals(foreignBaz, message.getRepeatedField(f("packed_enum" ),1));
+ }
+
+ /**
+ * Verifies that the reflection setters for the given.Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an
+ * appropriate assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ try {
+ builder.setField(f("optional_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.setField(f("optional_nested_message"),
+ (TestAllTypes.NestedMessage.Builder) null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ try {
+ builder.addRepeatedField(f("repeated_string"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_bytes"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_enum"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ try {
+ builder.addRepeatedField(f("repeated_nested_message"), null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+
+ /**
+ * Verifies that the reflection repeated setters for the given Builder object throw a
+ * NullPointerException if they are passed a null value. Uses Assert to throw an appropriate
+ * assertion failure, if the condition is not verified.
+ */
+ public void assertReflectionRepeatedSettersRejectNull(Message.Builder builder)
+ throws Exception {
+ builder.addRepeatedField(f("repeated_string"), "one");
+ try {
+ builder.setRepeatedField(f("repeated_string"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_bytes"), toBytes("one"));
+ try {
+ builder.setRepeatedField(f("repeated_bytes"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(f("repeated_nested_enum"), nestedBaz);
+ try {
+ builder.setRepeatedField(f("repeated_nested_enum"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+
+ builder.addRepeatedField(
+ f("repeated_nested_message"),
+ TestAllTypes.NestedMessage.newBuilder().setBb(218).build());
+ try {
+ builder.setRepeatedField(f("repeated_nested_message"), 0, null);
+ Assert.fail("Exception was not thrown");
+ } catch (NullPointerException e) {
+ // We expect this exception.
+ }
+ }
+ }
+
+ /**
+ * @param filePath The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static String readTextFromFile(String filePath) {
+ return readBytesFromFile(filePath).toStringUtf8();
+ }
+
+ private static File getTestDataDir() {
+ // Search each parent directory looking for "src/google/protobuf".
+ File ancestor = new File(System.getProperty("protobuf.dir", "."));
+ String initialPath = ancestor.getAbsolutePath();
+ try {
+ ancestor = ancestor.getCanonicalFile();
+ } catch (IOException e) {
+ throw new RuntimeException(
+ "Couldn't get canonical name of working directory.", e);
+ }
+ while (ancestor != null && ancestor.exists()) {
+ if (new File(ancestor, "src/google/protobuf").exists()) {
+ return new File(ancestor, "src/google/protobuf/testdata");
+ }
+ ancestor = ancestor.getParentFile();
+ }
+
+ throw new RuntimeException(
+ "Could not find golden files. This test must be run from within the " +
+ "protobuf source package so that it can read test data files from the " +
+ "C++ source tree: " + initialPath);
+ }
+
+ /**
+ * @param filename The path relative to
+ * {@link #getTestDataDir}.
+ */
+ public static ByteString readBytesFromFile(String filename) {
+ File fullPath = new File(getTestDataDir(), filename);
+ try {
+ RandomAccessFile file = new RandomAccessFile(fullPath, "r");
+ byte[] content = new byte[(int) file.length()];
+ file.readFully(content);
+ return ByteString.copyFrom(content);
+ } catch (IOException e) {
+ // Throw a RuntimeException here so that we can call this function from
+ // static initializers.
+ throw new IllegalArgumentException(
+ "Couldn't read file: " + fullPath.getPath(), e);
+ }
+ }
+
+ /**
+ * Get the bytes of the "golden message". This is a serialized TestAllTypes
+ * with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypes.Builder)}, but it is loaded from a file
+ * on disk rather than generated dynamically. The file is actually generated
+ * by C++ code, so testing against it verifies compatibility with C++.
+ */
+ public static ByteString getGoldenMessage() {
+ if (goldenMessage == null) {
+ goldenMessage = readBytesFromFile("golden_message_oneof_implemented");
+ }
+ return goldenMessage;
+ }
+ private static ByteString goldenMessage = null;
+
+ /**
+ * Get the bytes of the "golden packed fields message". This is a serialized
+ * TestPackedTypes with all fields set as they would be by
+ * {@link #setPackedFields(TestPackedTypes.Builder)}, but it is loaded from a
+ * file on disk rather than generated dynamically. The file is actually
+ * generated by C++ code, so testing against it verifies compatibility with
+ * C++.
+ */
+ public static ByteString getGoldenPackedFieldsMessage() {
+ if (goldenPackedFieldsMessage == null) {
+ goldenPackedFieldsMessage =
+ readBytesFromFile("golden_packed_fields_message");
+ }
+ return goldenPackedFieldsMessage;
+ }
+ private static ByteString goldenPackedFieldsMessage = null;
+
+ /**
+ * Mock implementation of {@link GeneratedMessage.BuilderParent} for testing.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+ public static class MockBuilderParent
+ implements GeneratedMessage.BuilderParent {
+
+ private int invalidations;
+
+ @Override
+ public void markDirty() {
+ invalidations++;
+ }
+
+ public int getInvalidationCount() {
+ return invalidations;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtilLite.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
new file mode 100644
index 0000000000..8f33fa14ab
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TestUtilLite.java
@@ -0,0 +1,559 @@
+// 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 static com.google.protobuf.UnittestLite.OptionalGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.RepeatedGroup_extension_lite;
+import static com.google.protobuf.UnittestLite.defaultBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultCordExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.defaultUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofStringExtensionLite;
+import static com.google.protobuf.UnittestLite.oneofUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalCordExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalPublicImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.optionalUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.packedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.packedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.packedUint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBoolExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedBytesExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedCordExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedDoubleExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedFloatExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedForeignMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedGroupExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedImportMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedInt64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedLazyMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedEnumExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedNestedMessageExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSfixed64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedSint64ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedStringPieceExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint32ExtensionLite;
+import static com.google.protobuf.UnittestLite.repeatedUint64ExtensionLite;
+
+import com.google.protobuf.UnittestImportLite.ImportEnumLite;
+import com.google.protobuf.UnittestImportLite.ImportMessageLite;
+import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+
+/**
+ * Contains methods for setting fields of {@code TestAllTypesLite}, {@code TestAllExtensionsLite},
+ * and {@code TestPackedExtensionsLite}. This is analogous to the functionality in TestUtil.java but
+ * does not depend on the presence of any non-lite protos.
+ *
+ * <p>This code is not to be used outside of {@code com.google.protobuf} and
+ * subpackages.
+ */
+public final class TestUtilLite {
+ private TestUtilLite() {}
+
+ /** Helper to convert a String to ByteString. */
+ static ByteString toBytes(String str) {
+ return ByteString.copyFrom(str.getBytes(Internal.UTF_8));
+ }
+
+ /**
+ * Get a {@code TestAllTypesLite.Builder} with all fields set as they would be by
+ * {@link #setAllFields(TestAllTypesLite.Builder)}.
+ */
+ public static TestAllTypesLite.Builder getAllLiteSetBuilder() {
+ TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+ setAllFields(builder);
+ return builder;
+ }
+
+ /**
+ * Get a {@code TestAllExtensionsLite} with all fields set as they would be by
+ * {@link #setAllExtensions(TestAllExtensionsLite.Builder)}.
+ */
+ public static TestAllExtensionsLite getAllLiteExtensionsSet() {
+ TestAllExtensionsLite.Builder builder = TestAllExtensionsLite.newBuilder();
+ setAllExtensions(builder);
+ return builder.build();
+ }
+
+ public static TestPackedExtensionsLite getLitePackedExtensionsSet() {
+ TestPackedExtensionsLite.Builder builder = TestPackedExtensionsLite.newBuilder();
+ setPackedExtensions(builder);
+ return builder.build();
+ }
+
+ /**
+ * Set every field of {@code builder} to the values expected by
+ * {@code assertAllFieldsSet()}.
+ */
+ public static void setAllFields(TestAllTypesLite.Builder builder) {
+ builder.setOptionalInt32 (101);
+ builder.setOptionalInt64 (102);
+ builder.setOptionalUint32 (103);
+ builder.setOptionalUint64 (104);
+ builder.setOptionalSint32 (105);
+ builder.setOptionalSint64 (106);
+ builder.setOptionalFixed32 (107);
+ builder.setOptionalFixed64 (108);
+ builder.setOptionalSfixed32(109);
+ builder.setOptionalSfixed64(110);
+ builder.setOptionalFloat (111);
+ builder.setOptionalDouble (112);
+ builder.setOptionalBool (true);
+ builder.setOptionalString ("115");
+ builder.setOptionalBytes (toBytes("116"));
+
+ builder.setOptionalGroup(
+ TestAllTypesLite.OptionalGroup.newBuilder().setA(117).build());
+ builder.setOptionalNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+ builder.setOptionalForeignMessage(
+ ForeignMessageLite.newBuilder().setC(119).build());
+ builder.setOptionalImportMessage(
+ ImportMessageLite.newBuilder().setD(120).build());
+ builder.setOptionalPublicImportMessage(
+ PublicImportMessageLite.newBuilder().setE(126).build());
+ builder.setOptionalLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+ builder.setOptionalNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+ builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+ builder.setOptionalImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+ builder.setOptionalStringPiece("124");
+ builder.setOptionalCord("125");
+
+ // -----------------------------------------------------------------
+
+ builder.addRepeatedInt32 (201);
+ builder.addRepeatedInt64 (202);
+ builder.addRepeatedUint32 (203);
+ builder.addRepeatedUint64 (204);
+ builder.addRepeatedSint32 (205);
+ builder.addRepeatedSint64 (206);
+ builder.addRepeatedFixed32 (207);
+ builder.addRepeatedFixed64 (208);
+ builder.addRepeatedSfixed32(209);
+ builder.addRepeatedSfixed64(210);
+ builder.addRepeatedFloat (211);
+ builder.addRepeatedDouble (212);
+ builder.addRepeatedBool (true);
+ builder.addRepeatedString ("215");
+ builder.addRepeatedBytes (toBytes("216"));
+
+ builder.addRepeatedGroup(
+ TestAllTypesLite.RepeatedGroup.newBuilder().setA(217).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+ builder.addRepeatedForeignMessage(
+ ForeignMessageLite.newBuilder().setC(219).build());
+ builder.addRepeatedImportMessage(
+ ImportMessageLite.newBuilder().setD(220).build());
+ builder.addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+ builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAR);
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR);
+ builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAR);
+
+ builder.addRepeatedStringPiece("224");
+ builder.addRepeatedCord("225");
+
+ // Add a second one of each field.
+ builder.addRepeatedInt32 (301);
+ builder.addRepeatedInt64 (302);
+ builder.addRepeatedUint32 (303);
+ builder.addRepeatedUint64 (304);
+ builder.addRepeatedSint32 (305);
+ builder.addRepeatedSint64 (306);
+ builder.addRepeatedFixed32 (307);
+ builder.addRepeatedFixed64 (308);
+ builder.addRepeatedSfixed32(309);
+ builder.addRepeatedSfixed64(310);
+ builder.addRepeatedFloat (311);
+ builder.addRepeatedDouble (312);
+ builder.addRepeatedBool (false);
+ builder.addRepeatedString ("315");
+ builder.addRepeatedBytes (toBytes("316"));
+
+ builder.addRepeatedGroup(
+ TestAllTypesLite.RepeatedGroup.newBuilder().setA(317).build());
+ builder.addRepeatedNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+ builder.addRepeatedForeignMessage(
+ ForeignMessageLite.newBuilder().setC(319).build());
+ builder.addRepeatedImportMessage(
+ ImportMessageLite.newBuilder().setD(320).build());
+ builder.addRepeatedLazyMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+ builder.addRepeatedNestedEnum (TestAllTypesLite.NestedEnum.BAZ);
+ builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAZ);
+ builder.addRepeatedImportEnum (ImportEnumLite.IMPORT_LITE_BAZ);
+
+ builder.addRepeatedStringPiece("324");
+ builder.addRepeatedCord("325");
+
+ // -----------------------------------------------------------------
+
+ builder.setDefaultInt32 (401);
+ builder.setDefaultInt64 (402);
+ builder.setDefaultUint32 (403);
+ builder.setDefaultUint64 (404);
+ builder.setDefaultSint32 (405);
+ builder.setDefaultSint64 (406);
+ builder.setDefaultFixed32 (407);
+ builder.setDefaultFixed64 (408);
+ builder.setDefaultSfixed32(409);
+ builder.setDefaultSfixed64(410);
+ builder.setDefaultFloat (411);
+ builder.setDefaultDouble (412);
+ builder.setDefaultBool (false);
+ builder.setDefaultString ("415");
+ builder.setDefaultBytes (toBytes("416"));
+
+ builder.setDefaultNestedEnum (TestAllTypesLite.NestedEnum.FOO);
+ builder.setDefaultForeignEnum(ForeignEnumLite.FOREIGN_LITE_FOO);
+ builder.setDefaultImportEnum (ImportEnumLite.IMPORT_LITE_FOO);
+
+ builder.setDefaultStringPiece("424");
+ builder.setDefaultCord("425");
+
+ builder.setOneofUint32(601);
+ builder.setOneofNestedMessage(
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+ builder.setOneofString("603");
+ builder.setOneofBytes(toBytes("604"));
+ }
+
+ /**
+ * Get an unmodifiable {@link ExtensionRegistryLite} containing all the
+ * extensions of {@code TestAllExtensionsLite}.
+ */
+ public static ExtensionRegistryLite getExtensionRegistryLite() {
+ ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance();
+ registerAllExtensionsLite(registry);
+ return registry.getUnmodifiable();
+ }
+
+ /**
+ * Register all of {@code TestAllExtensionsLite}'s extensions with the
+ * given {@link ExtensionRegistryLite}.
+ */
+ public static void registerAllExtensionsLite(ExtensionRegistryLite registry) {
+ UnittestLite.registerAllExtensions(registry);
+ }
+
+ // ===================================================================
+ // Lite extensions
+
+ /**
+ * Set every field of {@code message} to the values expected by
+ * {@code assertAllExtensionsSet()}.
+ */
+ public static void setAllExtensions(TestAllExtensionsLite.Builder message) {
+ message.setExtension(optionalInt32ExtensionLite , 101);
+ message.setExtension(optionalInt64ExtensionLite , 102L);
+ message.setExtension(optionalUint32ExtensionLite , 103);
+ message.setExtension(optionalUint64ExtensionLite , 104L);
+ message.setExtension(optionalSint32ExtensionLite , 105);
+ message.setExtension(optionalSint64ExtensionLite , 106L);
+ message.setExtension(optionalFixed32ExtensionLite , 107);
+ message.setExtension(optionalFixed64ExtensionLite , 108L);
+ message.setExtension(optionalSfixed32ExtensionLite, 109);
+ message.setExtension(optionalSfixed64ExtensionLite, 110L);
+ message.setExtension(optionalFloatExtensionLite , 111F);
+ message.setExtension(optionalDoubleExtensionLite , 112D);
+ message.setExtension(optionalBoolExtensionLite , true);
+ message.setExtension(optionalStringExtensionLite , "115");
+ message.setExtension(optionalBytesExtensionLite , toBytes("116"));
+
+ message.setExtension(optionalGroupExtensionLite,
+ OptionalGroup_extension_lite.newBuilder().setA(117).build());
+ message.setExtension(optionalNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(118).build());
+ message.setExtension(optionalForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(119).build());
+ message.setExtension(optionalImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(120).build());
+ message.setExtension(optionalPublicImportMessageExtensionLite,
+ PublicImportMessageLite.newBuilder().setE(126).build());
+ message.setExtension(optionalLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(127).build());
+
+ message.setExtension(optionalNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.setExtension(optionalForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.setExtension(optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.setExtension(optionalStringPieceExtensionLite, "124");
+ message.setExtension(optionalCordExtensionLite, "125");
+
+ // -----------------------------------------------------------------
+
+ message.addExtension(repeatedInt32ExtensionLite , 201);
+ message.addExtension(repeatedInt64ExtensionLite , 202L);
+ message.addExtension(repeatedUint32ExtensionLite , 203);
+ message.addExtension(repeatedUint64ExtensionLite , 204L);
+ message.addExtension(repeatedSint32ExtensionLite , 205);
+ message.addExtension(repeatedSint64ExtensionLite , 206L);
+ message.addExtension(repeatedFixed32ExtensionLite , 207);
+ message.addExtension(repeatedFixed64ExtensionLite , 208L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 209);
+ message.addExtension(repeatedSfixed64ExtensionLite, 210L);
+ message.addExtension(repeatedFloatExtensionLite , 211F);
+ message.addExtension(repeatedDoubleExtensionLite , 212D);
+ message.addExtension(repeatedBoolExtensionLite , true);
+ message.addExtension(repeatedStringExtensionLite , "215");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("216"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(217).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(218).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(219).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(220).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(227).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAR);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAR);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "224");
+ message.addExtension(repeatedCordExtensionLite, "225");
+
+ // Add a second one of each field.
+ message.addExtension(repeatedInt32ExtensionLite , 301);
+ message.addExtension(repeatedInt64ExtensionLite , 302L);
+ message.addExtension(repeatedUint32ExtensionLite , 303);
+ message.addExtension(repeatedUint64ExtensionLite , 304L);
+ message.addExtension(repeatedSint32ExtensionLite , 305);
+ message.addExtension(repeatedSint64ExtensionLite , 306L);
+ message.addExtension(repeatedFixed32ExtensionLite , 307);
+ message.addExtension(repeatedFixed64ExtensionLite , 308L);
+ message.addExtension(repeatedSfixed32ExtensionLite, 309);
+ message.addExtension(repeatedSfixed64ExtensionLite, 310L);
+ message.addExtension(repeatedFloatExtensionLite , 311F);
+ message.addExtension(repeatedDoubleExtensionLite , 312D);
+ message.addExtension(repeatedBoolExtensionLite , false);
+ message.addExtension(repeatedStringExtensionLite , "315");
+ message.addExtension(repeatedBytesExtensionLite , toBytes("316"));
+
+ message.addExtension(repeatedGroupExtensionLite,
+ RepeatedGroup_extension_lite.newBuilder().setA(317).build());
+ message.addExtension(repeatedNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(318).build());
+ message.addExtension(repeatedForeignMessageExtensionLite,
+ ForeignMessageLite.newBuilder().setC(319).build());
+ message.addExtension(repeatedImportMessageExtensionLite,
+ ImportMessageLite.newBuilder().setD(320).build());
+ message.addExtension(repeatedLazyMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(327).build());
+
+ message.addExtension(repeatedNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.BAZ);
+ message.addExtension(repeatedForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ message.addExtension(repeatedImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ);
+
+ message.addExtension(repeatedStringPieceExtensionLite, "324");
+ message.addExtension(repeatedCordExtensionLite, "325");
+
+ // -----------------------------------------------------------------
+
+ message.setExtension(defaultInt32ExtensionLite , 401);
+ message.setExtension(defaultInt64ExtensionLite , 402L);
+ message.setExtension(defaultUint32ExtensionLite , 403);
+ message.setExtension(defaultUint64ExtensionLite , 404L);
+ message.setExtension(defaultSint32ExtensionLite , 405);
+ message.setExtension(defaultSint64ExtensionLite , 406L);
+ message.setExtension(defaultFixed32ExtensionLite , 407);
+ message.setExtension(defaultFixed64ExtensionLite , 408L);
+ message.setExtension(defaultSfixed32ExtensionLite, 409);
+ message.setExtension(defaultSfixed64ExtensionLite, 410L);
+ message.setExtension(defaultFloatExtensionLite , 411F);
+ message.setExtension(defaultDoubleExtensionLite , 412D);
+ message.setExtension(defaultBoolExtensionLite , false);
+ message.setExtension(defaultStringExtensionLite , "415");
+ message.setExtension(defaultBytesExtensionLite , toBytes("416"));
+
+ message.setExtension(defaultNestedEnumExtensionLite, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(defaultForeignEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(defaultImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(defaultStringPieceExtensionLite, "424");
+ message.setExtension(defaultCordExtensionLite, "425");
+
+ message.setExtension(oneofUint32ExtensionLite, 601);
+ message.setExtension(oneofNestedMessageExtensionLite,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(602).build());
+ message.setExtension(oneofStringExtensionLite, "603");
+ message.setExtension(oneofBytesExtensionLite, toBytes("604"));
+ }
+
+ // -------------------------------------------------------------------
+
+ /**
+ * Modify the repeated extensions of {@code message} to contain the values
+ * expected by {@code assertRepeatedExtensionsModified()}.
+ */
+ public static void modifyRepeatedExtensions(
+ TestAllExtensionsLite.Builder message) {
+ message.setExtension(repeatedInt32ExtensionLite , 1, 501);
+ message.setExtension(repeatedInt64ExtensionLite , 1, 502L);
+ message.setExtension(repeatedUint32ExtensionLite , 1, 503);
+ message.setExtension(repeatedUint64ExtensionLite , 1, 504L);
+ message.setExtension(repeatedSint32ExtensionLite , 1, 505);
+ message.setExtension(repeatedSint64ExtensionLite , 1, 506L);
+ message.setExtension(repeatedFixed32ExtensionLite , 1, 507);
+ message.setExtension(repeatedFixed64ExtensionLite , 1, 508L);
+ message.setExtension(repeatedSfixed32ExtensionLite, 1, 509);
+ message.setExtension(repeatedSfixed64ExtensionLite, 1, 510L);
+ message.setExtension(repeatedFloatExtensionLite , 1, 511F);
+ message.setExtension(repeatedDoubleExtensionLite , 1, 512D);
+ message.setExtension(repeatedBoolExtensionLite , 1, true);
+ message.setExtension(repeatedStringExtensionLite , 1, "515");
+ message.setExtension(repeatedBytesExtensionLite , 1, toBytes("516"));
+
+ message.setExtension(repeatedGroupExtensionLite, 1,
+ RepeatedGroup_extension_lite.newBuilder().setA(517).build());
+ message.setExtension(repeatedNestedMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(518).build());
+ message.setExtension(repeatedForeignMessageExtensionLite, 1,
+ ForeignMessageLite.newBuilder().setC(519).build());
+ message.setExtension(repeatedImportMessageExtensionLite, 1,
+ ImportMessageLite.newBuilder().setD(520).build());
+ message.setExtension(repeatedLazyMessageExtensionLite, 1,
+ TestAllTypesLite.NestedMessage.newBuilder().setBb(527).build());
+
+ message.setExtension(repeatedNestedEnumExtensionLite , 1, TestAllTypesLite.NestedEnum.FOO);
+ message.setExtension(repeatedForeignEnumExtensionLite, 1, ForeignEnumLite.FOREIGN_LITE_FOO);
+ message.setExtension(repeatedImportEnumExtensionLite , 1, ImportEnumLite.IMPORT_LITE_FOO);
+
+ message.setExtension(repeatedStringPieceExtensionLite, 1, "524");
+ message.setExtension(repeatedCordExtensionLite, 1, "525");
+ }
+
+ public static void setPackedExtensions(TestPackedExtensionsLite.Builder message) {
+ message.addExtension(packedInt32ExtensionLite , 601);
+ message.addExtension(packedInt64ExtensionLite , 602L);
+ message.addExtension(packedUint32ExtensionLite , 603);
+ message.addExtension(packedUint64ExtensionLite , 604L);
+ message.addExtension(packedSint32ExtensionLite , 605);
+ message.addExtension(packedSint64ExtensionLite , 606L);
+ message.addExtension(packedFixed32ExtensionLite , 607);
+ message.addExtension(packedFixed64ExtensionLite , 608L);
+ message.addExtension(packedSfixed32ExtensionLite, 609);
+ message.addExtension(packedSfixed64ExtensionLite, 610L);
+ message.addExtension(packedFloatExtensionLite , 611F);
+ message.addExtension(packedDoubleExtensionLite , 612D);
+ message.addExtension(packedBoolExtensionLite , true);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAR);
+ // Add a second one of each field.
+ message.addExtension(packedInt32ExtensionLite , 701);
+ message.addExtension(packedInt64ExtensionLite , 702L);
+ message.addExtension(packedUint32ExtensionLite , 703);
+ message.addExtension(packedUint64ExtensionLite , 704L);
+ message.addExtension(packedSint32ExtensionLite , 705);
+ message.addExtension(packedSint64ExtensionLite , 706L);
+ message.addExtension(packedFixed32ExtensionLite , 707);
+ message.addExtension(packedFixed64ExtensionLite , 708L);
+ message.addExtension(packedSfixed32ExtensionLite, 709);
+ message.addExtension(packedSfixed64ExtensionLite, 710L);
+ message.addExtension(packedFloatExtensionLite , 711F);
+ message.addExtension(packedDoubleExtensionLite , 712D);
+ message.addExtension(packedBoolExtensionLite , false);
+ message.addExtension(packedEnumExtensionLite, ForeignEnumLite.FOREIGN_LITE_BAZ);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java
new file mode 100644
index 0000000000..e338af2112
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java
@@ -0,0 +1,182 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/**
+ * Test @{link TextFormatParseInfoTree}.
+ */
+public class TextFormatParseInfoTreeTest extends TestCase {
+
+ private static final Descriptor DESCRIPTOR = TestAllTypes.getDescriptor();
+ private static final FieldDescriptor OPTIONAL_INT32 =
+ DESCRIPTOR.findFieldByName("optional_int32");
+ private static final FieldDescriptor OPTIONAL_BOOLEAN =
+ DESCRIPTOR.findFieldByName("optional_boolean");
+ private static final FieldDescriptor REPEATED_INT32 =
+ DESCRIPTOR.findFieldByName("repeated_int32");
+ private static final FieldDescriptor OPTIONAL_NESTED_MESSAGE =
+ DESCRIPTOR.findFieldByName("optional_nested_message");
+ private static final FieldDescriptor REPEATED_NESTED_MESSAGE =
+ DESCRIPTOR.findFieldByName("repeated_nested_message");
+ private static final FieldDescriptor FIELD_BB =
+ TestAllTypes.NestedMessage.getDescriptor().findFieldByName("bb");
+
+ private static final TextFormatParseLocation LOC0 = TextFormatParseLocation.create(1, 2);
+ private static final TextFormatParseLocation LOC1 = TextFormatParseLocation.create(2, 3);
+
+ private TextFormatParseInfoTree.Builder rootBuilder;
+
+ @Override
+ public void setUp() {
+ rootBuilder = TextFormatParseInfoTree.builder();
+ }
+
+ public void testBuildEmptyParseTree() {
+ TextFormatParseInfoTree tree = rootBuilder.build();
+ assertTrue(tree.getLocations(null).isEmpty());
+ }
+
+ public void testGetLocationReturnsSingleLocation() {
+ rootBuilder.setLocation(OPTIONAL_INT32, LOC0);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertEquals(LOC0, root.getLocation(OPTIONAL_INT32, 0));
+ assertEquals(1, root.getLocations(OPTIONAL_INT32).size());
+ }
+
+ public void testGetLocationsReturnsNoParseLocationsForUnknownField() {
+ assertTrue(rootBuilder.build().getLocations(OPTIONAL_INT32).isEmpty());
+ rootBuilder.setLocation(OPTIONAL_BOOLEAN, LOC0);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertTrue(root.getLocations(OPTIONAL_INT32).isEmpty());
+ assertEquals(LOC0, root.getLocations(OPTIONAL_BOOLEAN).get(0));
+ }
+
+ public void testGetLocationThrowsIllegalArgumentExceptionForUnknownField() {
+ rootBuilder.setLocation(REPEATED_INT32, LOC0);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ try {
+ root.getNestedTree(OPTIONAL_INT32, 0);
+ fail("Did not detect unknown field");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ }
+
+ public void testGetLocationThrowsIllegalArgumentExceptionForInvalidIndex() {
+ TextFormatParseInfoTree root = rootBuilder.setLocation(OPTIONAL_INT32, LOC0).build();
+ try {
+ root.getLocation(OPTIONAL_INT32, 1);
+ fail("Invalid index not detected");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ try {
+ root.getLocation(OPTIONAL_INT32, -1);
+ fail("Negative index not detected");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ }
+
+ public void testGetLocationsReturnsMultipleLocations() {
+ rootBuilder.setLocation(REPEATED_INT32, LOC0);
+ rootBuilder.setLocation(REPEATED_INT32, LOC1);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertEquals(LOC0, root.getLocation(REPEATED_INT32, 0));
+ assertEquals(LOC1, root.getLocation(REPEATED_INT32, 1));
+ assertEquals(2, root.getLocations(REPEATED_INT32).size());
+ }
+
+ public void testGetNestedTreeThrowsIllegalArgumentExceptionForUnknownField() {
+ rootBuilder.setLocation(REPEATED_INT32, LOC0);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ try {
+ root.getNestedTree(OPTIONAL_NESTED_MESSAGE, 0);
+ fail("Did not detect unknown field");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ }
+
+ public void testGetNestedTreesReturnsNoParseInfoTreesForUnknownField() {
+ rootBuilder.setLocation(REPEATED_INT32, LOC0);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertTrue(root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).isEmpty());
+ }
+
+ public void testGetNestedTreeThrowsIllegalArgumentExceptionForInvalidIndex() {
+ rootBuilder.setLocation(REPEATED_INT32, LOC0);
+ rootBuilder.getBuilderForSubMessageField(OPTIONAL_NESTED_MESSAGE);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ try {
+ root.getNestedTree(OPTIONAL_NESTED_MESSAGE, 1);
+ fail("Submessage index that is too large not detected");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ try {
+ rootBuilder.build().getNestedTree(OPTIONAL_NESTED_MESSAGE, -1);
+ fail("Invalid submessage index (-1) not detected");
+ } catch (IllegalArgumentException expected) {
+ // pass
+ }
+ }
+
+ public void testGetNestedTreesReturnsSingleTree() {
+ rootBuilder.getBuilderForSubMessageField(OPTIONAL_NESTED_MESSAGE);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertEquals(1, root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).size());
+ TextFormatParseInfoTree subtree = root.getNestedTrees(OPTIONAL_NESTED_MESSAGE).get(0);
+ assertNotNull(subtree);
+ }
+
+ public void testGetNestedTreesReturnsMultipleTrees() {
+ TextFormatParseInfoTree.Builder subtree1Builder =
+ rootBuilder.getBuilderForSubMessageField(REPEATED_NESTED_MESSAGE);
+ subtree1Builder.getBuilderForSubMessageField(FIELD_BB);
+ subtree1Builder.getBuilderForSubMessageField(FIELD_BB);
+ TextFormatParseInfoTree.Builder subtree2Builder =
+ rootBuilder.getBuilderForSubMessageField(REPEATED_NESTED_MESSAGE);
+ subtree2Builder.getBuilderForSubMessageField(FIELD_BB);
+ TextFormatParseInfoTree root = rootBuilder.build();
+ assertEquals(2, root.getNestedTrees(REPEATED_NESTED_MESSAGE).size());
+ assertEquals(
+ 2, root.getNestedTrees(REPEATED_NESTED_MESSAGE).get(0).getNestedTrees(FIELD_BB).size());
+ assertEquals(
+ 1, root.getNestedTrees(REPEATED_NESTED_MESSAGE).get(1).getNestedTrees(FIELD_BB).size());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java
new file mode 100644
index 0000000000..c42bfa6e71
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java
@@ -0,0 +1,86 @@
+// 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 junit.framework.TestCase;
+
+/**
+ * Test @{link TextFormatParseLocation}.
+ */
+public class TextFormatParseLocationTest extends TestCase {
+
+ public void testCreateEmpty() {
+ TextFormatParseLocation location = TextFormatParseLocation.create(-1, -1);
+ assertEquals(TextFormatParseLocation.EMPTY, location);
+ }
+
+ public void testCreate() {
+ TextFormatParseLocation location = TextFormatParseLocation.create(2, 1);
+ assertEquals(2, location.getLine());
+ assertEquals(1, location.getColumn());
+ }
+
+ public void testCreateThrowsIllegalArgumentExceptionForInvalidIndex() {
+ try {
+ TextFormatParseLocation.create(-1, 0);
+ fail("Should throw IllegalArgumentException if line is less than 0");
+ } catch (IllegalArgumentException unused) {
+ // pass
+ }
+ try {
+ TextFormatParseLocation.create(0, -1);
+ fail("Should throw, column < 0");
+ } catch (IllegalArgumentException unused) {
+ // pass
+ }
+ }
+
+ public void testHashCode() {
+ TextFormatParseLocation loc0 = TextFormatParseLocation.create(2, 1);
+ TextFormatParseLocation loc1 = TextFormatParseLocation.create(2, 1);
+
+ assertEquals(loc0.hashCode(), loc1.hashCode());
+ assertEquals(
+ TextFormatParseLocation.EMPTY.hashCode(), TextFormatParseLocation.EMPTY.hashCode());
+ }
+
+ public void testEquals() {
+ TextFormatParseLocation loc0 = TextFormatParseLocation.create(2, 1);
+ TextFormatParseLocation loc1 = TextFormatParseLocation.create(1, 2);
+ TextFormatParseLocation loc2 = TextFormatParseLocation.create(2, 2);
+ TextFormatParseLocation loc3 = TextFormatParseLocation.create(2, 1);
+
+ assertEquals(loc0, loc3);
+ assertNotSame(loc0, loc1);
+ assertNotSame(loc0, loc2);
+ assertNotSame(loc1, loc2);
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
new file mode 100644
index 0000000000..6a91b02f03
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -0,0 +1,1153 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto.OneString;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+import java.io.StringReader;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link TextFormat}.
+ *
+ * TODO(wenboz): ExtensionTest and rest of text_format_unittest.cc.
+ *
+ * @author wenboz@google.com (Wenbo Zhu)
+ */
+public class TextFormatTest extends TestCase {
+
+ // A basic string with different escapable characters for testing.
+ private final static String kEscapeTestString =
+ "\"A string with ' characters \n and \r newlines and \t tabs and \001 "
+ + "slashes \\";
+
+ // A representation of the above string with all the characters escaped.
+ private final static String kEscapeTestStringEscaped =
+ "\\\"A string with \\' characters \\n and \\r newlines "
+ + "and \\t tabs and \\001 slashes \\\\";
+
+ private static String allFieldsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_data_oneof_implemented.txt");
+ private static String allExtensionsSetText = TestUtil.readTextFromFile(
+ "text_format_unittest_extensions_data.txt");
+
+ private static String exoticText =
+ "repeated_int32: -1\n" +
+ "repeated_int32: -2147483648\n" +
+ "repeated_int64: -1,\n" +
+ "repeated_int64: -9223372036854775808\n" +
+ "repeated_uint32: 4294967295\n" +
+ "repeated_uint32: 2147483648\n" +
+ "repeated_uint64: 18446744073709551615\n" +
+ "repeated_uint64: 9223372036854775808\n" +
+ "repeated_double: 123.0\n" +
+ "repeated_double: 123.5\n" +
+ "repeated_double: 0.125\n" +
+ "repeated_double: .125\n" +
+ "repeated_double: -.125\n" +
+ "repeated_double: 1.23E17\n" +
+ "repeated_double: 1.23E+17\n" +
+ "repeated_double: -1.23e-17\n" +
+ "repeated_double: .23e+17\n" +
+ "repeated_double: -.23E17\n" +
+ "repeated_double: 1.235E22\n" +
+ "repeated_double: 1.235E-18\n" +
+ "repeated_double: 123.456789\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n" +
+ "repeated_string: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"" +
+ "\\341\\210\\264\"\n" +
+ "repeated_bytes: \"\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\376\"\n";
+
+ private static String canonicalExoticText =
+ exoticText.replace(": .", ": 0.").replace(": -.", ": -0.") // short-form double
+ .replace("23e", "23E").replace("E+", "E").replace("0.23E17", "2.3E16").replace(",", "");
+
+ private String messageSetText =
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 123\n" +
+ "}\n" +
+ "[protobuf_unittest.TestMessageSetExtension2] {\n" +
+ " str: \"foo\"\n" +
+ "}\n";
+
+ private String messageSetTextWithRepeatedExtension =
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 123\n" +
+ "}\n" +
+ "[protobuf_unittest.TestMessageSetExtension1] {\n" +
+ " i: 456\n" +
+ "}\n";
+
+
+ private final TextFormat.Parser parserWithOverwriteForbidden =
+ TextFormat.Parser.newBuilder()
+ .setSingularOverwritePolicy(
+ SingularOverwritePolicy.FORBID_SINGULAR_OVERWRITES)
+ .build();
+
+ private final TextFormat.Parser defaultParser =
+ TextFormat.Parser.newBuilder().build();
+
+ /** Print TestAllTypes and compare with golden file. */
+ public void testPrintMessage() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllTypes as Builder and compare with golden file. */
+ public void testPrintMessageBuilder() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllSetBuilder());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allFieldsSetText, javaText);
+ }
+
+ /** Print TestAllExtensions and compare with golden file. */
+ public void testPrintExtensions() throws Exception {
+ String javaText = TextFormat.printToString(TestUtil.getAllExtensionsSet());
+
+ // Java likes to add a trailing ".0" to floats and doubles. C printf
+ // (with %g format) does not. Our golden files are used for both
+ // C++ and Java TextFormat classes, so we need to conform.
+ javaText = javaText.replace(".0\n", "\n");
+
+ assertEquals(allExtensionsSetText, javaText);
+ }
+
+ // Creates an example unknown field set.
+ private UnknownFieldSet makeUnknownFieldSet() {
+ return UnknownFieldSet.newBuilder()
+ .addField(5,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addFixed32(2)
+ .addFixed64(3)
+ .addLengthDelimited(ByteString.copyFromUtf8("4"))
+ .addGroup(
+ UnknownFieldSet.newBuilder()
+ .addField(10,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(5)
+ .build())
+ .build())
+ .build())
+ .addField(8,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .addVarint(2)
+ .addVarint(3)
+ .build())
+ .addField(15,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0xABCDEF1234567890L)
+ .addFixed32(0xABCD1234)
+ .addFixed64(0xABCDEF1234567890L)
+ .build())
+ .build();
+ }
+
+ public void testPrintUnknownFields() throws Exception {
+ // Test printing of unknown fields in a message.
+
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(makeUnknownFieldSet())
+ .build();
+
+ assertEquals(
+ "5: 1\n" +
+ "5: 0x00000002\n" +
+ "5: 0x0000000000000003\n" +
+ "5: \"4\"\n" +
+ "5 {\n" +
+ " 10: 5\n" +
+ "}\n" +
+ "8: 1\n" +
+ "8: 2\n" +
+ "8: 3\n" +
+ "15: 12379813812177893520\n" +
+ "15: 0xabcd1234\n" +
+ "15: 0xabcdef1234567890\n",
+ TextFormat.printToString(message));
+ }
+
+ public void testPrintField() throws Exception {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"\n",
+ TextFormat.printFieldToString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message {\n bb: 42\n}\n",
+ TextFormat.printFieldToString(optionalField, value));
+ }
+
+ /**
+ * Helper to construct a ByteString from a String containing only 8-bit
+ * characters. The characters are converted directly to bytes, *not*
+ * encoded using UTF-8.
+ */
+ private ByteString bytes(String str) {
+ return ByteString.copyFrom(str.getBytes(Internal.ISO_8859_1));
+ }
+
+ /**
+ * Helper to construct a ByteString from a bunch of bytes. The inputs are
+ * actually ints so that I can use hex notation and not get stupid errors
+ * about precision.
+ */
+ private ByteString bytes(int... bytesAsInts) {
+ byte[] bytes = new byte[bytesAsInts.length];
+ for (int i = 0; i < bytesAsInts.length; i++) {
+ bytes[i] = (byte) bytesAsInts[i];
+ }
+ return ByteString.copyFrom(bytes);
+ }
+
+ public void testPrintExotic() throws Exception {
+ Message message = TestAllTypes.newBuilder()
+ // Signed vs. unsigned numbers.
+ .addRepeatedInt32 (-1)
+ .addRepeatedUint32(-1)
+ .addRepeatedInt64 (-1)
+ .addRepeatedUint64(-1)
+
+ .addRepeatedInt32 (1 << 31)
+ .addRepeatedUint32(1 << 31)
+ .addRepeatedInt64 (1L << 63)
+ .addRepeatedUint64(1L << 63)
+
+ // Floats of various precisions and exponents.
+ .addRepeatedDouble(123)
+ .addRepeatedDouble(123.5)
+ .addRepeatedDouble(0.125)
+ .addRepeatedDouble(.125)
+ .addRepeatedDouble(-.125)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(123e15)
+ .addRepeatedDouble(-1.23e-17)
+ .addRepeatedDouble(.23e17)
+ .addRepeatedDouble(-23e15)
+ .addRepeatedDouble(123.5e20)
+ .addRepeatedDouble(123.5e-20)
+ .addRepeatedDouble(123.456789)
+ .addRepeatedDouble(Double.POSITIVE_INFINITY)
+ .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+ .addRepeatedDouble(Double.NaN)
+
+ // Strings and bytes that needing escaping.
+ .addRepeatedString("\0\001\007\b\f\n\r\t\013\\\'\"\u1234")
+ .addRepeatedBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\u00fe"))
+ .build();
+
+ assertEquals(canonicalExoticText, message.toString());
+ }
+
+ public void testPrintMessageSet() throws Exception {
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .build();
+
+ assertEquals(messageSetText, messageSet.toString());
+ }
+
+ // =================================================================
+
+ public void testParse() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(allFieldsSetText, builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseReader() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(new StringReader(allFieldsSetText), builder);
+ TestUtil.assertAllFieldsSet(builder.build());
+ }
+
+ public void testParseExtensions() throws Exception {
+ TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
+ TextFormat.merge(allExtensionsSetText,
+ TestUtil.getExtensionRegistry(),
+ builder);
+ TestUtil.assertAllExtensionsSet(builder.build());
+ }
+
+ public void testParseCompatibility() throws Exception {
+ String original = "repeated_float: inf\n" +
+ "repeated_float: -inf\n" +
+ "repeated_float: nan\n" +
+ "repeated_float: inff\n" +
+ "repeated_float: -inff\n" +
+ "repeated_float: nanf\n" +
+ "repeated_float: 1.0f\n" +
+ "repeated_float: infinityf\n" +
+ "repeated_float: -Infinityf\n" +
+ "repeated_double: infinity\n" +
+ "repeated_double: -infinity\n" +
+ "repeated_double: nan\n";
+ String canonical = "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_float: NaN\n" +
+ "repeated_float: 1.0\n" +
+ "repeated_float: Infinity\n" +
+ "repeated_float: -Infinity\n" +
+ "repeated_double: Infinity\n" +
+ "repeated_double: -Infinity\n" +
+ "repeated_double: NaN\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(original, builder);
+ assertEquals(canonical, builder.build().toString());
+ }
+
+ public void testParseExotic() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(exoticText, builder);
+
+ // Too lazy to check things individually. Don't try to debug this
+ // if testPrintExotic() is failing.
+ assertEquals(canonicalExoticText, builder.build().toString());
+ }
+
+ public void testParseMessageSet() throws Exception {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+ TextFormat.merge(messageSetText, extensionRegistry, builder);
+ TestMessageSet messageSet = builder.build();
+
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension1.messageSetExtension));
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertTrue(messageSet.hasExtension(
+ TestMessageSetExtension2.messageSetExtension));
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ builder = TestMessageSet.newBuilder();
+ TextFormat.merge(messageSetTextWithRepeatedExtension, extensionRegistry,
+ builder);
+ messageSet = builder.build();
+ assertEquals(456, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testParseMessageSetWithOverwriteForbidden() throws Exception {
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ TestMessageSet.Builder builder = TestMessageSet.newBuilder();
+ parserWithOverwriteForbidden.merge(
+ messageSetText, extensionRegistry, builder);
+ TestMessageSet messageSet = builder.build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ builder = TestMessageSet.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ messageSetTextWithRepeatedExtension, extensionRegistry, builder);
+ fail("expected parse exception");
+ } catch (TextFormat.ParseException e) {
+ assertEquals("6:1: Non-repeated field "
+ + "\"protobuf_unittest.TestMessageSetExtension1.message_set_extension\""
+ + " cannot be overwritten.",
+ e.getMessage());
+ }
+ }
+
+ public void testParseNumericEnum() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_nested_enum: 2", builder);
+ assertEquals(TestAllTypes.NestedEnum.BAR, builder.getOptionalNestedEnum());
+ }
+
+ public void testParseAngleBrackets() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("OptionalGroup: < a: 1 >", builder);
+ assertTrue(builder.hasOptionalGroup());
+ assertEquals(1, builder.getOptionalGroup().getA());
+ }
+
+ public void testParseComment() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(
+ "# this is a comment\n" +
+ "optional_int32: 1 # another comment\n" +
+ "optional_int64: 2\n" +
+ "# EOF comment", builder);
+ assertEquals(1, builder.getOptionalInt32());
+ assertEquals(2, builder.getOptionalInt64());
+ }
+
+ private void assertParseError(String error, String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ TextFormat.merge(text, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+
+ private void assertParseErrorWithOverwriteForbidden(String error,
+ String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+ private TestAllTypes assertParseSuccessWithOverwriteForbidden(
+ String text) throws TextFormat.ParseException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ parserWithOverwriteForbidden.merge(
+ text, TestUtil.getExtensionRegistry(), builder);
+ return builder.build();
+ }
+
+ public void testParseErrors() throws Exception {
+ assertParseError(
+ "1:16: Expected \":\".",
+ "optional_int32 123");
+ assertParseError(
+ "1:23: Expected identifier. Found '?'",
+ "optional_nested_enum: ?");
+ assertParseError(
+ "1:18: Couldn't parse integer: Number must be positive: -1",
+ "optional_uint32: -1");
+ assertParseError(
+ "1:17: Couldn't parse integer: Number out of range for 32-bit signed " +
+ "integer: 82301481290849012385230157",
+ "optional_int32: 82301481290849012385230157");
+ assertParseError(
+ "1:16: Expected \"true\" or \"false\".",
+ "optional_bool: maybe");
+ assertParseError(
+ "1:16: Expected \"true\" or \"false\".",
+ "optional_bool: 2");
+ assertParseError(
+ "1:18: Expected string.",
+ "optional_string: 123");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe\n" +
+ "optional_int32: 123");
+ assertParseError(
+ "1:18: Invalid escape sequence: '\\z'",
+ "optional_string: \"\\z\"");
+ assertParseError(
+ "1:18: String missing ending quote.",
+ "optional_string: \"ueoauaoe\n" +
+ "optional_int32: 123");
+ assertParseError(
+ "1:2: Input contains unknown fields and/or extensions:\n" +
+ "1:2:\tprotobuf_unittest.TestAllTypes.[nosuchext]",
+ "[nosuchext]: 123");
+ assertParseError(
+ "1:20: Extension \"protobuf_unittest.optional_int32_extension\" does " +
+ "not extend message type \"protobuf_unittest.TestAllTypes\".",
+ "[protobuf_unittest.optional_int32_extension]: 123");
+ assertParseError(
+ "1:1: Input contains unknown fields and/or extensions:\n" +
+ "1:1:\tprotobuf_unittest.TestAllTypes.nosuchfield",
+ "nosuchfield: 123");
+ assertParseError(
+ "1:21: Expected \">\".",
+ "OptionalGroup < a: 1");
+ assertParseError(
+ "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+ "value named \"NO_SUCH_VALUE\".",
+ "optional_nested_enum: NO_SUCH_VALUE");
+ assertParseError(
+ "1:23: Enum type \"protobuf_unittest.TestAllTypes.NestedEnum\" has no " +
+ "value with number 123.",
+ "optional_nested_enum: 123");
+
+ // Delimiters must match.
+ assertParseError(
+ "1:22: Expected identifier. Found '}'",
+ "OptionalGroup < a: 1 }");
+ assertParseError(
+ "1:22: Expected identifier. Found '>'",
+ "OptionalGroup { a: 1 >");
+ }
+
+ // =================================================================
+
+ public void testEscape() throws Exception {
+ // Escape sequences.
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeBytes(bytes("\0\001\007\b\f\n\r\t\013\\\'\"\177")));
+ assertEquals("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\"\\177",
+ TextFormat.escapeText("\0\001\007\b\f\n\r\t\013\\\'\"\177"));
+ assertEquals(bytes("\0\001\007\b\f\n\r\t\013\\\'\""),
+ TextFormat.unescapeBytes("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+ assertEquals("\0\001\007\b\f\n\r\t\013\\\'\"",
+ TextFormat.unescapeText("\\000\\001\\a\\b\\f\\n\\r\\t\\v\\\\\\'\\\""));
+ assertEquals(kEscapeTestStringEscaped,
+ TextFormat.escapeText(kEscapeTestString));
+ assertEquals(kEscapeTestString,
+ TextFormat.unescapeText(kEscapeTestStringEscaped));
+
+ // Invariant
+ assertEquals("hello",
+ TextFormat.escapeBytes(bytes("hello")));
+ assertEquals("hello",
+ TextFormat.escapeText("hello"));
+ assertEquals(bytes("hello"),
+ TextFormat.unescapeBytes("hello"));
+ assertEquals("hello",
+ TextFormat.unescapeText("hello"));
+
+ // Unicode handling.
+ assertEquals("\\341\\210\\264", TextFormat.escapeText("\u1234"));
+ assertEquals("\\341\\210\\264",
+ TextFormat.escapeBytes(bytes(0xe1, 0x88, 0xb4)));
+ assertEquals("\u1234", TextFormat.unescapeText("\\341\\210\\264"));
+ assertEquals(bytes(0xe1, 0x88, 0xb4),
+ TextFormat.unescapeBytes("\\341\\210\\264"));
+ assertEquals("\u1234", TextFormat.unescapeText("\\xe1\\x88\\xb4"));
+ assertEquals(bytes(0xe1, 0x88, 0xb4),
+ TextFormat.unescapeBytes("\\xe1\\x88\\xb4"));
+
+ // Handling of strings with unescaped Unicode characters > 255.
+ final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+ ByteString zhByteString = ByteString.copyFromUtf8(zh);
+ assertEquals(zhByteString, TextFormat.unescapeBytes(zh));
+
+ // Errors.
+ try {
+ TextFormat.unescapeText("\\x");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+
+ try {
+ TextFormat.unescapeText("\\z");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+
+ try {
+ TextFormat.unescapeText("\\");
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.InvalidEscapeSequenceException e) {
+ // success
+ }
+ }
+
+ public void testParseInteger() throws Exception {
+ assertEquals( 0, TextFormat.parseInt32( "0"));
+ assertEquals( 1, TextFormat.parseInt32( "1"));
+ assertEquals( -1, TextFormat.parseInt32( "-1"));
+ assertEquals( 12345, TextFormat.parseInt32( "12345"));
+ assertEquals( -12345, TextFormat.parseInt32( "-12345"));
+ assertEquals( 2147483647, TextFormat.parseInt32( "2147483647"));
+ assertEquals(-2147483648, TextFormat.parseInt32("-2147483648"));
+
+ assertEquals( 0, TextFormat.parseUInt32( "0"));
+ assertEquals( 1, TextFormat.parseUInt32( "1"));
+ assertEquals( 12345, TextFormat.parseUInt32( "12345"));
+ assertEquals( 2147483647, TextFormat.parseUInt32("2147483647"));
+ assertEquals((int) 2147483648L, TextFormat.parseUInt32("2147483648"));
+ assertEquals((int) 4294967295L, TextFormat.parseUInt32("4294967295"));
+
+ assertEquals( 0L, TextFormat.parseInt64( "0"));
+ assertEquals( 1L, TextFormat.parseInt64( "1"));
+ assertEquals( -1L, TextFormat.parseInt64( "-1"));
+ assertEquals( 12345L, TextFormat.parseInt64( "12345"));
+ assertEquals( -12345L, TextFormat.parseInt64( "-12345"));
+ assertEquals( 2147483647L, TextFormat.parseInt64( "2147483647"));
+ assertEquals(-2147483648L, TextFormat.parseInt64("-2147483648"));
+ assertEquals( 4294967295L, TextFormat.parseInt64( "4294967295"));
+ assertEquals( 4294967296L, TextFormat.parseInt64( "4294967296"));
+ assertEquals(9223372036854775807L,
+ TextFormat.parseInt64("9223372036854775807"));
+ assertEquals(-9223372036854775808L,
+ TextFormat.parseInt64("-9223372036854775808"));
+
+ assertEquals( 0L, TextFormat.parseUInt64( "0"));
+ assertEquals( 1L, TextFormat.parseUInt64( "1"));
+ assertEquals( 12345L, TextFormat.parseUInt64( "12345"));
+ assertEquals( 2147483647L, TextFormat.parseUInt64( "2147483647"));
+ assertEquals( 4294967295L, TextFormat.parseUInt64( "4294967295"));
+ assertEquals( 4294967296L, TextFormat.parseUInt64( "4294967296"));
+ assertEquals(9223372036854775807L,
+ TextFormat.parseUInt64("9223372036854775807"));
+ assertEquals(-9223372036854775808L,
+ TextFormat.parseUInt64("9223372036854775808"));
+ assertEquals(-1L, TextFormat.parseUInt64("18446744073709551615"));
+
+ // Hex
+ assertEquals(0x1234abcd, TextFormat.parseInt32("0x1234abcd"));
+ assertEquals(-0x1234abcd, TextFormat.parseInt32("-0x1234abcd"));
+ assertEquals(-1, TextFormat.parseUInt64("0xffffffffffffffff"));
+ assertEquals(0x7fffffffffffffffL,
+ TextFormat.parseInt64("0x7fffffffffffffff"));
+
+ // Octal
+ assertEquals(01234567, TextFormat.parseInt32("01234567"));
+
+ // Out-of-range
+ try {
+ TextFormat.parseInt32("2147483648");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt32("-2147483649");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt32("4294967296");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt32("-1");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt64("9223372036854775808");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseInt64("-9223372036854775809");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt64("18446744073709551616");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ try {
+ TextFormat.parseUInt64("-1");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+
+ // Not a number.
+ try {
+ TextFormat.parseInt32("abcd");
+ fail("Should have thrown an exception.");
+ } catch (NumberFormatException e) {
+ // success
+ }
+ }
+
+ public void testParseString() throws Exception {
+ final String zh = "\u9999\u6e2f\u4e0a\u6d77\ud84f\udf80\u8c50\u9280\u884c";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + zh + "\"", builder);
+ assertEquals(zh, builder.getOptionalString());
+ }
+
+ public void testParseLongString() throws Exception {
+ String longText =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"" + longText + "\"", builder);
+ assertEquals(longText, builder.getOptionalString());
+ }
+
+ public void testParseBoolean() throws Exception {
+ String goodText =
+ "repeated_bool: t repeated_bool : 0\n" +
+ "repeated_bool :f repeated_bool:1\n" +
+ "repeated_bool: False repeated_bool: True";
+ String goodTextCanonical =
+ "repeated_bool: true\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: true\n" +
+ "repeated_bool: false\n" +
+ "repeated_bool: true\n";
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(goodText, builder);
+ assertEquals(goodTextCanonical, builder.build().toString());
+
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool:2", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ try {
+ TestAllTypes.Builder badBuilder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_bool: foo", badBuilder);
+ fail("Should have thrown an exception.");
+ } catch (TextFormat.ParseException e) {
+ // success
+ }
+ }
+
+ public void testParseAdjacentStringLiterals() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge("optional_string: \"foo\" 'corge' \"grault\"", builder);
+ assertEquals("foocorgegrault", builder.getOptionalString());
+ }
+
+ public void testPrintFieldValue() throws Exception {
+ assertPrintFieldValue("\"Hello\"", "Hello", "repeated_string");
+ assertPrintFieldValue("123.0", 123f, "repeated_float");
+ assertPrintFieldValue("123.0", 123d, "repeated_double");
+ assertPrintFieldValue("123", 123, "repeated_int32");
+ assertPrintFieldValue("123", 123L, "repeated_int64");
+ assertPrintFieldValue("true", true, "repeated_bool");
+ assertPrintFieldValue("4294967295", 0xFFFFFFFF, "repeated_uint32");
+ assertPrintFieldValue("18446744073709551615", 0xFFFFFFFFFFFFFFFFL,
+ "repeated_uint64");
+ assertPrintFieldValue("\"\\001\\002\\003\"",
+ ByteString.copyFrom(new byte[] {1, 2, 3}), "repeated_bytes");
+ }
+
+ private void assertPrintFieldValue(String expect, Object value,
+ String fieldName) throws Exception {
+ StringBuilder sb = new StringBuilder();
+ TextFormat.printFieldValue(
+ TestAllTypes.getDescriptor().findFieldByName(fieldName),
+ value, sb);
+ assertEquals(expect, sb.toString());
+ }
+
+ public void testShortDebugString() {
+ assertEquals("optional_nested_message { bb: 42 } repeated_int32: 1"
+ + " repeated_uint32: 2",
+ TextFormat.shortDebugString(TestAllTypes.newBuilder()
+ .addRepeatedInt32(1)
+ .addRepeatedUint32(2)
+ .setOptionalNestedMessage(
+ NestedMessage.newBuilder().setBb(42).build())
+ .build()));
+ }
+
+ public void testShortDebugString_field() {
+ final FieldDescriptor dataField =
+ OneString.getDescriptor().findFieldByName("data");
+ assertEquals(
+ "data: \"test data\"",
+ TextFormat.shortDebugString(dataField, "test data"));
+
+ final FieldDescriptor optionalField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_message");
+ final Object value = NestedMessage.newBuilder().setBb(42).build();
+
+ assertEquals(
+ "optional_nested_message { bb: 42 }",
+ TextFormat.shortDebugString(optionalField, value));
+ }
+
+ public void testShortDebugString_unknown() {
+ assertEquals("5: 1 5: 0x00000002 5: 0x0000000000000003 5: \"4\" 5 { 10: 5 }"
+ + " 8: 1 8: 2 8: 3 15: 12379813812177893520 15: 0xabcd1234 15:"
+ + " 0xabcdef1234567890",
+ TextFormat.shortDebugString(makeUnknownFieldSet()));
+ }
+
+ public void testPrintToUnicodeString() throws Exception {
+ assertEquals(
+ "optional_string: \"abc\u3042efg\"\n" +
+ "optional_bytes: \"\\343\\201\\202\"\n" +
+ "repeated_string: \"\u3093XYZ\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("abc\u3042efg")
+ .setOptionalBytes(bytes(0xe3, 0x81, 0x82))
+ .addRepeatedString("\u3093XYZ")
+ .build()));
+
+ // Double quotes and backslashes should be escaped
+ assertEquals(
+ "optional_string: \"a\\\\bc\\\"ef\\\"g\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("a\\bc\"ef\"g")
+ .build()));
+
+ // Test escaping roundtrip
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalString("a\\bc\\\"ef\"g")
+ .build();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
+ }
+
+ public void testPrintToUnicodeStringWithNewlines() throws Exception {
+ // No newlines at start and end
+ assertEquals("optional_string: \"test newlines\\n\\nin\\nstring\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("test newlines\n\nin\nstring")
+ .build()));
+
+ // Newlines at start and end
+ assertEquals("optional_string: \"\\ntest\\nnewlines\\n\\nin\\nstring\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+ .build()));
+
+ // Strings with 0, 1 and 2 newlines.
+ assertEquals("optional_string: \"\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("")
+ .build()));
+ assertEquals("optional_string: \"\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\n")
+ .build()));
+ assertEquals("optional_string: \"\\n\\n\"\n",
+ TextFormat.printToUnicodeString(TestAllTypes.newBuilder()
+ .setOptionalString("\n\n")
+ .build()));
+
+ // Test escaping roundtrip
+ TestAllTypes message = TestAllTypes.newBuilder()
+ .setOptionalString("\ntest\nnewlines\n\nin\nstring\n")
+ .build();
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), builder);
+ assertEquals(message.getOptionalString(), builder.getOptionalString());
+ }
+
+ public void testPrintToUnicodeString_unknown() {
+ assertEquals(
+ "1: \"\\343\\201\\202\"\n",
+ TextFormat.printToUnicodeString(UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(bytes(0xe3, 0x81, 0x82)).build())
+ .build()));
+ }
+
+
+ public void testParseNonRepeatedFields() throws Exception {
+ assertParseSuccessWithOverwriteForbidden(
+ "repeated_int32: 1\n" +
+ "repeated_int32: 2\n");
+ assertParseSuccessWithOverwriteForbidden(
+ "RepeatedGroup { a: 1 }\n" +
+ "RepeatedGroup { a: 2 }\n");
+ assertParseSuccessWithOverwriteForbidden(
+ "repeated_nested_message { bb: 1 }\n" +
+ "repeated_nested_message { bb: 2 }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "3:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optional_int32\" " +
+ "cannot be overwritten.",
+ "optional_int32: 1\n" +
+ "optional_bool: true\n" +
+ "optional_int32: 1\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optionalgroup\" " +
+ "cannot be overwritten.",
+ "OptionalGroup { a: 1 }\n" +
+ "OptionalGroup { }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:33: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.optional_nested_message\" " +
+ "cannot be overwritten.",
+ "optional_nested_message { }\n" +
+ "optional_nested_message { bb: 3 }\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:16: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.default_int32\" " +
+ "cannot be overwritten.",
+ "default_int32: 41\n" + // the default value
+ "default_int32: 41\n");
+ assertParseErrorWithOverwriteForbidden(
+ "2:17: Non-repeated field " +
+ "\"protobuf_unittest.TestAllTypes.default_string\" " +
+ "cannot be overwritten.",
+ "default_string: \"zxcv\"\n" +
+ "default_string: \"asdf\"\n");
+ }
+
+ public void testParseShortRepeatedFormOfRepeatedFields() throws Exception {
+ assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: [FOREIGN_FOO, FOREIGN_BAR]");
+ assertParseSuccessWithOverwriteForbidden("repeated_int32: [ 1, 2 ]\n");
+ assertParseSuccessWithOverwriteForbidden("RepeatedGroup [{ a: 1 },{ a: 2 }]\n");
+ assertParseSuccessWithOverwriteForbidden("repeated_nested_message [{ bb: 1 }, { bb: 2 }]\n");
+ }
+
+ public void testParseShortRepeatedFormOfEmptyRepeatedFields() throws Exception {
+ assertParseSuccessWithOverwriteForbidden("repeated_foreign_enum: []");
+ assertParseSuccessWithOverwriteForbidden("repeated_int32: []\n");
+ assertParseSuccessWithOverwriteForbidden("RepeatedGroup []\n");
+ assertParseSuccessWithOverwriteForbidden("repeated_nested_message []\n");
+ }
+
+ public void testParseShortRepeatedFormWithTrailingComma() throws Exception {
+ assertParseErrorWithOverwriteForbidden(
+ "1:38: Expected identifier. Found \']\'",
+ "repeated_foreign_enum: [FOREIGN_FOO, ]\n");
+ assertParseErrorWithOverwriteForbidden(
+ "1:22: Couldn't parse integer: For input string: \"]\"",
+ "repeated_int32: [ 1, ]\n");
+ assertParseErrorWithOverwriteForbidden(
+ "1:25: Expected \"{\".",
+ "RepeatedGroup [{ a: 1 },]\n");
+ assertParseErrorWithOverwriteForbidden(
+ "1:37: Expected \"{\".",
+ "repeated_nested_message [{ bb: 1 }, ]\n");
+ }
+
+ public void testParseShortRepeatedFormOfNonRepeatedFields() throws Exception {
+ assertParseErrorWithOverwriteForbidden(
+ "1:17: Couldn't parse integer: For input string: \"[\"",
+ "optional_int32: [1]\n");
+ assertParseErrorWithOverwriteForbidden(
+ "1:17: Couldn't parse integer: For input string: \"[\"",
+ "optional_int32: []\n");
+ }
+
+ // =======================================================================
+ // test oneof
+
+ public void testOneofTextFormat() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestUtil.setOneof(builder);
+ TestOneof2 message = builder.build();
+ TestOneof2.Builder dest = TestOneof2.newBuilder();
+ TextFormat.merge(TextFormat.printToUnicodeString(message), dest);
+ TestUtil.assertOneofSet(dest.build());
+ }
+
+ public void testOneofOverwriteForbidden() throws Exception {
+ String input = "foo_string: \"stringvalue\" foo_int: 123";
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ try {
+ parserWithOverwriteForbidden.merge(
+ input, TestUtil.getExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals("1:36: Field \"protobuf_unittest.TestOneof2.foo_int\""
+ + " is specified along with field \"protobuf_unittest.TestOneof2.foo_string\","
+ + " another member of oneof \"foo\".", e.getMessage());
+ }
+ }
+
+ public void testOneofOverwriteAllowed() throws Exception {
+ String input = "foo_string: \"stringvalue\" foo_int: 123";
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ defaultParser.merge(input, TestUtil.getExtensionRegistry(), builder);
+ // Only the last value sticks.
+ TestOneof2 oneof = builder.build();
+ assertFalse(oneof.hasFooString());
+ assertTrue(oneof.hasFooInt());
+ }
+
+ // =======================================================================
+ // test location information
+
+ public void testParseInfoTreeBuilding() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ TextFormatParseInfoTree.Builder treeBuilder = TextFormatParseInfoTree.builder();
+ // Set to allow unknown fields
+ TextFormat.Parser parser =
+ TextFormat.Parser.newBuilder()
+ .setParseInfoTreeBuilder(treeBuilder)
+ .build();
+
+ final String stringData =
+ "optional_int32: 1\n"
+ + "optional_int64: 2\n"
+ + " optional_double: 2.4\n"
+ + "repeated_int32: 5\n"
+ + "repeated_int32: 10\n"
+ + "optional_nested_message <\n"
+ + " bb: 78\n"
+ + ">\n"
+ + "repeated_nested_message <\n"
+ + " bb: 79\n"
+ + ">\n"
+ + "repeated_nested_message <\n"
+ + " bb: 80\n"
+ + ">";
+
+ parser.merge(stringData, builder);
+ TextFormatParseInfoTree tree = treeBuilder.build();
+
+ // Verify that the tree has the correct positions.
+ assertLocation(tree, descriptor, "optional_int32", 0, 0, 0);
+ assertLocation(tree, descriptor, "optional_int64", 0, 1, 0);
+ assertLocation(tree, descriptor, "optional_double", 0, 2, 2);
+
+ assertLocation(tree, descriptor, "repeated_int32", 0, 3, 0);
+ assertLocation(tree, descriptor, "repeated_int32", 1, 4, 0);
+
+ assertLocation(tree, descriptor, "optional_nested_message", 0, 5, 0);
+ assertLocation(tree, descriptor, "repeated_nested_message", 0, 8, 0);
+ assertLocation(tree, descriptor, "repeated_nested_message", 1, 11, 0);
+
+ // Check for fields not set. For an invalid field, the location returned should be -1, -1.
+ assertLocation(tree, descriptor, "repeated_int64", 0, -1, -1);
+ assertLocation(tree, descriptor, "repeated_int32", 6, -1, -1);
+
+ // Verify inside the nested message.
+ FieldDescriptor nestedField = descriptor.findFieldByName("optional_nested_message");
+
+ TextFormatParseInfoTree nestedTree = tree.getNestedTrees(nestedField).get(0);
+ assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 6, 2);
+
+ // Verify inside another nested message.
+ nestedField = descriptor.findFieldByName("repeated_nested_message");
+ nestedTree = tree.getNestedTrees(nestedField).get(0);
+ assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 9, 2);
+
+ nestedTree = tree.getNestedTrees(nestedField).get(1);
+ assertLocation(nestedTree, nestedField.getMessageType(), "bb", 0, 12, 2);
+
+ // Verify a NULL tree for an unknown nested field.
+ try {
+ tree.getNestedTree(nestedField, 2);
+ fail("unknown nested field should throw");
+ } catch (IllegalArgumentException unused) {
+ // pass
+ }
+ }
+
+ private void assertLocation(
+ TextFormatParseInfoTree tree,
+ final Descriptor descriptor,
+ final String fieldName,
+ int index,
+ int line,
+ int column) {
+ List<TextFormatParseLocation> locs = tree.getLocations(descriptor.findFieldByName(fieldName));
+ if (index < locs.size()) {
+ TextFormatParseLocation location = locs.get(index);
+ TextFormatParseLocation expected = TextFormatParseLocation.create(line, column);
+ assertEquals(expected, location);
+ } else if (line != -1 && column != -1) {
+ fail(
+ String.format(
+ "Tree/descriptor/fieldname did not contain index %d, line %d column %d expected",
+ index,
+ line,
+ column));
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
new file mode 100644
index 0000000000..8f45976fb4
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
@@ -0,0 +1,255 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
+import com.google.protobuf.TextFormat.ParseException;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for protos that keep unknown enum values rather than discard
+ * them as unknown fields.
+ */
+public class UnknownEnumValueTest extends TestCase {
+ public void testUnknownEnumValues() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test serialization and parsing.
+ ByteString data = message.toByteString();
+ message = TestAllTypes.parseFrom(data);
+ assertEquals(4321, message.getOptionalNestedEnumValue());
+ assertEquals(5432, message.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, message.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, message.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, message.getPackedNestedEnum(0));
+
+ // Test toBuilder().
+ builder = message.toBuilder();
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test mergeFrom().
+ builder = TestAllTypes.newBuilder().mergeFrom(message);
+ assertEquals(4321, builder.getOptionalNestedEnumValue());
+ assertEquals(5432, builder.getRepeatedNestedEnumValue(0));
+ assertEquals(5432, builder.getRepeatedNestedEnumValueList().get(0).intValue());
+ assertEquals(6543, builder.getPackedNestedEnumValue(0));
+ // Returns UNRECOGNIZED if an enum type is requested.
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getOptionalNestedEnum());
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getRepeatedNestedEnumList().get(0));
+ assertEquals(TestAllTypes.NestedEnum.UNRECOGNIZED, builder.getPackedNestedEnum(0));
+
+ // Test equals() and hashCode()
+ TestAllTypes sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+
+ // Getting the numeric value of UNRECOGNIZED will throw an exception.
+ try {
+ TestAllTypes.NestedEnum.UNRECOGNIZED.getNumber();
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Setting an enum field to an UNRECOGNIZED value will throw an exception.
+ try {
+ builder.setOptionalNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ try {
+ builder.addRepeatedNestedEnum(builder.getOptionalNestedEnum());
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testUnknownEnumValueInReflectionApi() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ TestAllTypes message = builder.build();
+
+ // Getters will return unknown enum values as EnumValueDescriptor.
+ EnumValueDescriptor unknown4321 =
+ (EnumValueDescriptor) message.getField(optionalNestedEnumField);
+ EnumValueDescriptor unknown5432 =
+ (EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0);
+ EnumValueDescriptor unknown6543 =
+ (EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0);
+ assertEquals(4321, unknown4321.getNumber());
+ assertEquals(5432, unknown5432.getNumber());
+ assertEquals(6543, unknown6543.getNumber());
+
+ // Unknown EnumValueDescriptor will map to UNRECOGNIZED.
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown4321),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown5432),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+ assertEquals(
+ TestAllTypes.NestedEnum.valueOf(unknown6543),
+ TestAllTypes.NestedEnum.UNRECOGNIZED);
+
+ // Setters also accept unknown EnumValueDescriptor.
+ builder.setField(optionalNestedEnumField, unknown6543);
+ builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);
+ builder.setRepeatedField(packedNestedEnumField, 0, unknown5432);
+ message = builder.build();
+ // Like other descriptors, unknown EnumValueDescriptor can be compared by
+ // object identity.
+ assertTrue(unknown6543 == message.getField(optionalNestedEnumField));
+ assertTrue(unknown4321 == message.getRepeatedField(repeatedNestedEnumField, 0));
+ assertTrue(unknown5432 == message.getRepeatedField(packedNestedEnumField, 0));
+ }
+
+ public void testUnknownEnumValueWithDynamicMessage() throws Exception {
+ Descriptor descriptor = TestAllTypes.getDescriptor();
+ FieldDescriptor optionalNestedEnumField = descriptor.findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedNestedEnumField = descriptor.findFieldByName("repeated_nested_enum");
+ FieldDescriptor packedNestedEnumField = descriptor.findFieldByName("packed_nested_enum");
+ EnumDescriptor enumType = TestAllTypes.NestedEnum.getDescriptor();
+
+ Message dynamicMessageDefaultInstance = DynamicMessage.getDefaultInstance(descriptor);
+
+ Message.Builder builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message message = builder.build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based serialization/parsing implementation.
+ ByteString data = message.toByteString();
+ message = dynamicMessageDefaultInstance
+ .newBuilderForType()
+ .mergeFrom(data)
+ .build();
+ assertEquals(4321,
+ ((EnumValueDescriptor) message.getField(optionalNestedEnumField)).getNumber());
+ assertEquals(5432,
+ ((EnumValueDescriptor) message.getRepeatedField(repeatedNestedEnumField, 0)).getNumber());
+ assertEquals(6543,
+ ((EnumValueDescriptor) message.getRepeatedField(packedNestedEnumField, 0)).getNumber());
+
+ // Test reflection based equals()/hashCode().
+ builder = dynamicMessageDefaultInstance.newBuilderForType();
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(4321));
+ builder.addRepeatedField(repeatedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(5432));
+ builder.addRepeatedField(packedNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(6543));
+ Message sameMessage = builder.build();
+ assertEquals(message, sameMessage);
+ assertEquals(message.hashCode(), sameMessage.hashCode());
+ builder.setField(optionalNestedEnumField,
+ enumType.findValueByNumberCreatingIfUnknown(0));
+ Message differentMessage = builder.build();
+ assertFalse(message.equals(differentMessage));
+ }
+
+ public void testUnknownEnumValuesInTextFormat() {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ builder.setOptionalNestedEnumValue(4321);
+ builder.addRepeatedNestedEnumValue(5432);
+ builder.addPackedNestedEnumValue(6543);
+ TestAllTypes message = builder.build();
+
+ // We can print a message with unknown enum values.
+ String textData = TextFormat.printToString(message);
+ assertEquals(
+ "optional_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_4321\n"
+ + "repeated_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_5432\n"
+ + "packed_nested_enum: UNKNOWN_ENUM_VALUE_NestedEnum_6543\n", textData);
+
+ // Parsing unknown enum values will fail just like parsing other kinds of
+ // unknown fields.
+ try {
+ TextFormat.merge(textData, builder);
+ fail();
+ } catch (ParseException e) {
+ // expected.
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
new file mode 100644
index 0000000000..f8cb0aabbc
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
@@ -0,0 +1,334 @@
+// 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 com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestAllTypesLite;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
+import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link UnknownFieldSetLite}.
+ *
+ * @author dweis@google.com (Daniel Weis)
+ */
+public class UnknownFieldSetLiteTest extends TestCase {
+
+ public void testDefaultInstance() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testEmptyInstance() {
+ UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+
+ assertEquals(0, instance.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(instance));
+ assertEquals(UnknownFieldSetLite.getDefaultInstance(), instance);
+ }
+
+ public void testMergeFieldFrom() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+ instance.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString(), toByteString(instance));
+ }
+
+ public void testSerializedSize() throws IOException {
+ Foo foo = Foo.newBuilder()
+ .setValue(2)
+ .build();
+
+ CodedInputStream input = CodedInputStream.newInstance(foo.toByteArray());
+
+ UnknownFieldSetLite instance = UnknownFieldSetLite.newInstance();
+ instance.mergeFieldFrom(input.readTag(), input);
+
+ assertEquals(foo.toByteString().size(), instance.getSerializedSize());
+ }
+
+ public void testMergeVarintField() throws IOException {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.mergeVarintField(10, 2);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testMergeVarintField_negative() throws IOException {
+ UnknownFieldSetLite builder = UnknownFieldSetLite.newInstance();
+ builder.mergeVarintField(10, -6);
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(builder).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(-6, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSetLite unknownFields1 = UnknownFieldSetLite.newInstance();
+ unknownFields1.mergeVarintField(10, 2);
+
+ UnknownFieldSetLite unknownFields2 = UnknownFieldSetLite.newInstance();
+ unknownFields2.mergeVarintField(10, 2);
+
+ assertEquals(unknownFields1, unknownFields2);
+ assertEquals(unknownFields1.hashCode(), unknownFields2.hashCode());
+ assertFalse(unknownFields1.equals(UnknownFieldSetLite.getDefaultInstance()));
+ assertFalse(unknownFields1.hashCode() == UnknownFieldSetLite.getDefaultInstance().hashCode());
+ }
+
+ public void testMutableCopyOf() throws IOException {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.mergeVarintField(10, 2);
+ unknownFields = UnknownFieldSetLite.mutableCopyOf(unknownFields, unknownFields);
+ unknownFields.checkMutable();
+
+ CodedInputStream input =
+ CodedInputStream.newInstance(toByteString(unknownFields).toByteArray());
+
+ int tag = input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertFalse(input.isAtEnd());
+ input.readTag();
+ assertEquals(10, WireFormat.getTagFieldNumber(tag));
+ assertEquals(WireFormat.WIRETYPE_VARINT, WireFormat.getTagWireType(tag));
+ assertEquals(2, input.readUInt64());
+ assertTrue(input.isAtEnd());
+ }
+
+ public void testMutableCopyOf_empty() {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.mutableCopyOf(
+ UnknownFieldSetLite.getDefaultInstance(), UnknownFieldSetLite.getDefaultInstance());
+ unknownFields.checkMutable();
+
+ assertEquals(0, unknownFields.getSerializedSize());
+ assertEquals(ByteString.EMPTY, toByteString(unknownFields));
+ }
+
+ public void testRoundTrips() throws InvalidProtocolBufferException {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.fixed32, 44)
+ .setExtension(LiteEqualsAndHash.fixed64, 66L)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ Foo copy = Foo.parseFrom(foo.toByteArray());
+
+ assertEquals(foo.getSerializedSize(), copy.getSerializedSize());
+ assertFalse(foo.equals(copy));
+
+ Foo secondCopy = Foo.parseFrom(foo.toByteArray());
+ assertEquals(copy, secondCopy);
+
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ LiteEqualsAndHash.registerAllExtensions(extensionRegistry);
+ Foo copyOfCopy = Foo.parseFrom(copy.toByteArray(), extensionRegistry);
+
+ assertEquals(foo, copyOfCopy);
+ }
+
+ public void testMalformedBytes() throws Exception {
+ try {
+ Foo.parseFrom("this is a malformed protocol buffer".getBytes(Internal.UTF_8));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingStartGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(100, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMissingEndGroupTag() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMismatchingGroupTags() throws IOException {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteStringOutput);
+ output.writeTag(100, WireFormat.WIRETYPE_START_GROUP);
+ output.writeGroupNoTag(Foo.newBuilder().setValue(11).build());
+ output.writeTag(101, WireFormat.WIRETYPE_END_GROUP);
+ output.flush();
+
+ try {
+ Foo.parseFrom(byteStringOutput.toByteString());
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testTruncatedInput() {
+ Foo foo = Foo.newBuilder()
+ .setValue(1)
+ .setExtension(Bar.fooExt, Bar.newBuilder()
+ .setName("name")
+ .build())
+ .setExtension(LiteEqualsAndHash.varint, 22)
+ .setExtension(LiteEqualsAndHash.myGroup, LiteEqualsAndHash.MyGroup.newBuilder()
+ .setGroupValue("value")
+ .build())
+ .build();
+
+ try {
+ Foo.parseFrom(foo.toByteString().substring(0, foo.toByteString().size() - 10));
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testMakeImmutable() throws Exception {
+ UnknownFieldSetLite unknownFields = UnknownFieldSetLite.newInstance();
+ unknownFields.makeImmutable();
+
+ try {
+ unknownFields.mergeVarintField(1, 1);
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ try {
+ unknownFields.mergeLengthDelimitedField(2, ByteString.copyFromUtf8("hello"));
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ try {
+ unknownFields.mergeFieldFrom(1, CodedInputStream.newInstance(new byte[0]));
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ public void testEndToEnd() throws Exception {
+ TestAllTypesLite testAllTypes = TestAllTypesLite.getDefaultInstance();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.parseFrom(new byte[0]);
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.newBuilder().build();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ testAllTypes = TestAllTypesLite.newBuilder()
+ .setDefaultBool(true)
+ .build();
+ try {
+ testAllTypes.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+
+ TestAllExtensionsLite testAllExtensions = TestAllExtensionsLite.newBuilder()
+ .mergeFrom(TestAllExtensionsLite.newBuilder()
+ .setExtension(UnittestLite.optionalInt32ExtensionLite, 2)
+ .build().toByteArray())
+ .build();
+ try {
+ testAllExtensions.unknownFields.checkMutable();
+ fail();
+ } catch (UnsupportedOperationException expected) {}
+ }
+
+ private ByteString toByteString(UnknownFieldSetLite unknownFields) {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ try {
+ unknownFields.writeTo(output);
+ output.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return ByteString.copyFrom(byteArrayOutputStream.toByteArray());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
new file mode 100644
index 0000000000..f81e90b459
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
@@ -0,0 +1,652 @@
+// 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 protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.ForeignEnum;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestEmptyMessage;
+import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import java.util.Arrays;
+import java.util.Map;
+import junit.framework.TestCase;
+
+/**
+ * Tests related to unknown field handling.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class UnknownFieldSetTest extends TestCase {
+ @Override
+ public void setUp() throws Exception {
+ descriptor = TestAllTypes.getDescriptor();
+ allFields = TestUtil.getAllSet();
+ allFieldsData = allFields.toByteString();
+ emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
+ unknownFields = emptyMessage.getUnknownFields();
+ }
+
+ UnknownFieldSet.Field getField(String name) {
+ Descriptors.FieldDescriptor field = descriptor.findFieldByName(name);
+ assertNotNull(field);
+ return unknownFields.getField(field.getNumber());
+ }
+
+ // Constructs a protocol buffer which contains fields with all the same
+ // numbers as allFieldsData except that each field is some other wire
+ // type.
+ ByteString getBizarroData() throws Exception {
+ UnknownFieldSet.Builder bizarroFields = UnknownFieldSet.newBuilder();
+
+ UnknownFieldSet.Field varintField =
+ UnknownFieldSet.Field.newBuilder().addVarint(1).build();
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder().addFixed32(1).build();
+
+ for (Map.Entry<Integer, UnknownFieldSet.Field> entry :
+ unknownFields.asMap().entrySet()) {
+ if (entry.getValue().getVarintList().isEmpty()) {
+ // Original field is not a varint, so use a varint.
+ bizarroFields.addField(entry.getKey(), varintField);
+ } else {
+ // Original field *is* a varint, so use something else.
+ bizarroFields.addField(entry.getKey(), fixed32Field);
+ }
+ }
+
+ return bizarroFields.build().toByteString();
+ }
+
+ Descriptors.Descriptor descriptor;
+ TestAllTypes allFields;
+ ByteString allFieldsData;
+
+ // An empty message that has been parsed from allFieldsData. So, it has
+ // unknown fields of every type.
+ TestEmptyMessage emptyMessage;
+ UnknownFieldSet unknownFields;
+
+ // =================================================================
+
+ public void testVarint() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_int32");
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(allFields.getOptionalInt32(),
+ (long) field.getVarintList().get(0));
+ }
+
+ public void testFixed32() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed32");
+ assertEquals(1, field.getFixed32List().size());
+ assertEquals(allFields.getOptionalFixed32(),
+ (int) field.getFixed32List().get(0));
+ }
+
+ public void testFixed64() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_fixed64");
+ assertEquals(1, field.getFixed64List().size());
+ assertEquals(allFields.getOptionalFixed64(),
+ (long) field.getFixed64List().get(0));
+ }
+
+ public void testLengthDelimited() throws Exception {
+ UnknownFieldSet.Field field = getField("optional_bytes");
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals(allFields.getOptionalBytes(),
+ field.getLengthDelimitedList().get(0));
+ }
+
+ public void testGroup() throws Exception {
+ Descriptors.FieldDescriptor nestedFieldDescriptor =
+ TestAllTypes.OptionalGroup.getDescriptor().findFieldByName("a");
+ assertNotNull(nestedFieldDescriptor);
+
+ UnknownFieldSet.Field field = getField("optionalgroup");
+ assertEquals(1, field.getGroupList().size());
+
+ UnknownFieldSet group = field.getGroupList().get(0);
+ assertEquals(1, group.asMap().size());
+ assertTrue(group.hasField(nestedFieldDescriptor.getNumber()));
+
+ UnknownFieldSet.Field nestedField =
+ group.getField(nestedFieldDescriptor.getNumber());
+ assertEquals(1, nestedField.getVarintList().size());
+ assertEquals(allFields.getOptionalGroup().getA(),
+ (long) nestedField.getVarintList().get(0));
+ }
+
+ public void testSerialize() throws Exception {
+ // Check that serializing the UnknownFieldSet produces the original data
+ // again.
+ ByteString data = emptyMessage.toByteString();
+ assertEquals(allFieldsData, data);
+ }
+
+ public void testCopyFrom() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).build();
+
+ assertEquals(emptyMessage.toString(), message.toString());
+ }
+
+ public void testMergeFrom() throws Exception {
+ TestEmptyMessage source =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(2,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(2).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(4).build())
+ .build())
+ .build();
+ TestEmptyMessage destination =
+ TestEmptyMessage.newBuilder()
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1).build())
+ .addField(3,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(3).build())
+ .build())
+ .mergeFrom(source)
+ .build();
+
+ assertEquals(
+ "1: 1\n" +
+ "2: 2\n" +
+ "3: 3\n" +
+ "3: 4\n",
+ destination.toString());
+ }
+
+ public void testClear() throws Exception {
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clear().build();
+ assertTrue(fields.asMap().isEmpty());
+ }
+
+ public void testClearMessage() throws Exception {
+ TestEmptyMessage message =
+ TestEmptyMessage.newBuilder().mergeFrom(emptyMessage).clear().build();
+ assertEquals(0, message.getSerializedSize());
+ }
+
+ public void testClearField() throws Exception {
+ int fieldNumber = unknownFields.asMap().keySet().iterator().next();
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder().mergeFrom(unknownFields).clearField(fieldNumber).build();
+ assertFalse(fields.hasField(fieldNumber));
+ }
+
+ public void testParseKnownAndUnknown() throws Exception {
+ // Test mixing known and unknown fields when parsing.
+
+ UnknownFieldSet fields =
+ UnknownFieldSet.newBuilder(unknownFields)
+ .addField(123456,
+ UnknownFieldSet.Field.newBuilder().addVarint(654321).build())
+ .build();
+
+ ByteString data = fields.toByteString();
+ TestAllTypes destination = TestAllTypes.parseFrom(data);
+
+ TestUtil.assertAllFieldsSet(destination);
+ assertEquals(1, destination.getUnknownFields().asMap().size());
+
+ UnknownFieldSet.Field field =
+ destination.getUnknownFields().getField(123456);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(654321, (long) field.getVarintList().get(0));
+ }
+
+ public void testWrongTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(), allTypesMessage.toString());
+ }
+
+ public void testUnknownExtensions() throws Exception {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ TestEmptyMessageWithExtensions message =
+ TestEmptyMessageWithExtensions.parseFrom(allFieldsData);
+
+ assertEquals(unknownFields.asMap().size(),
+ message.getUnknownFields().asMap().size());
+ assertEquals(allFieldsData, message.toByteString());
+ }
+
+ public void testWrongExtensionTypeTreatedAsUnknown() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllExtensions allExtensionsMessage =
+ TestAllExtensions.parseFrom(bizarroData);
+ TestEmptyMessage emptyMessage = TestEmptyMessage.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ assertEquals(emptyMessage.toString(),
+ allExtensionsMessage.toString());
+ }
+
+ public void testParseUnknownEnumValue() throws Exception {
+ Descriptors.FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ Descriptors.FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ assertNotNull(singularField);
+ assertNotNull(repeatedField);
+
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(5) // not valid
+ .build())
+ .addField(repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(4) // not valid
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(6) // not valid
+ .build())
+ .build()
+ .toByteString();
+
+ {
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getOptionalNestedEnum());
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getRepeatedNestedEnumList());
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+
+ {
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+ }
+
+ public void testLargeVarint() throws Exception {
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(1,
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(0x7FFFFFFFFFFFFFFFL)
+ .build())
+ .build()
+ .toByteString();
+ UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data);
+ UnknownFieldSet.Field field = parsed.getField(1);
+ assertEquals(1, field.getVarintList().size());
+ assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0));
+ }
+
+ public void testEqualsAndHashCode() {
+ UnknownFieldSet.Field fixed32Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed32(1)
+ .build();
+ UnknownFieldSet.Field fixed64Field =
+ UnknownFieldSet.Field.newBuilder()
+ .addFixed64(1)
+ .build();
+ UnknownFieldSet.Field varIntField =
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(1)
+ .build();
+ UnknownFieldSet.Field lengthDelimitedField =
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.EMPTY)
+ .build();
+ UnknownFieldSet.Field groupField =
+ UnknownFieldSet.Field.newBuilder()
+ .addGroup(unknownFields)
+ .build();
+
+ UnknownFieldSet a =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed32Field)
+ .build();
+ UnknownFieldSet b =
+ UnknownFieldSet.newBuilder()
+ .addField(1, fixed64Field)
+ .build();
+ UnknownFieldSet c =
+ UnknownFieldSet.newBuilder()
+ .addField(1, varIntField)
+ .build();
+ UnknownFieldSet d =
+ UnknownFieldSet.newBuilder()
+ .addField(1, lengthDelimitedField)
+ .build();
+ UnknownFieldSet e =
+ UnknownFieldSet.newBuilder()
+ .addField(1, groupField)
+ .build();
+
+ checkEqualsIsConsistent(a);
+ checkEqualsIsConsistent(b);
+ checkEqualsIsConsistent(c);
+ checkEqualsIsConsistent(d);
+ checkEqualsIsConsistent(e);
+
+ checkNotEqual(a, b);
+ checkNotEqual(a, c);
+ checkNotEqual(a, d);
+ checkNotEqual(a, e);
+ checkNotEqual(b, c);
+ checkNotEqual(b, d);
+ checkNotEqual(b, e);
+ checkNotEqual(c, d);
+ checkNotEqual(c, e);
+ checkNotEqual(d, e);
+ }
+
+ /**
+ * Asserts that the given field sets are not equal and have different
+ * hash codes.
+ *
+ * @warning It's valid for non-equal objects to have the same hash code, so
+ * this test is stricter than it needs to be. However, this should happen
+ * relatively rarely.
+ */
+ private void checkNotEqual(UnknownFieldSet s1, UnknownFieldSet s2) {
+ String equalsError = String.format("%s should not be equal to %s", s1, s2);
+ assertFalse(equalsError, s1.equals(s2));
+ assertFalse(equalsError, s2.equals(s1));
+
+ assertFalse(
+ String.format("%s should have a different hash code from %s", s1, s2),
+ s1.hashCode() == s2.hashCode());
+ }
+
+ /**
+ * Asserts that the given field sets are equal and have identical hash codes.
+ */
+ private void checkEqualsIsConsistent(UnknownFieldSet set) {
+ // Object should be equal to itself.
+ assertEquals(set, set);
+
+ // Object should be equal to a copy of itself.
+ UnknownFieldSet copy = UnknownFieldSet.newBuilder(set).build();
+ assertEquals(set, copy);
+ assertEquals(copy, set);
+ assertEquals(set.hashCode(), copy.hashCode());
+ }
+
+ // =================================================================
+
+ public void testSerializeLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ assertEquals(allFieldsData.size(), emptyMessageLite.getSerializedSize());
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ TestUtil.assertAllFieldsSet(message);
+ assertEquals(allFieldsData, data);
+ }
+
+ public void testAllExtensionsLite() throws Exception {
+ TestAllExtensions allExtensions = TestUtil.getAllExtensionsSet();
+ ByteString allExtensionsData = allExtensions.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parser().parseFrom(allExtensionsData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertAllExtensionsSet(message);
+ assertEquals(allExtensionsData, data);
+ }
+
+ public void testAllPackedFieldsLite() throws Exception {
+ TestPackedTypes allPackedFields = TestUtil.getPackedSet();
+ ByteString allPackedData = allPackedFields.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allPackedData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestPackedTypes message =
+ TestPackedTypes.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertPackedFieldsSet(message);
+ assertEquals(allPackedData, data);
+ }
+
+ public void testAllPackedExtensionsLite() throws Exception {
+ TestPackedExtensions allPackedExtensions = TestUtil.getPackedExtensionsSet();
+ ByteString allPackedExtensionsData = allPackedExtensions.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allPackedExtensionsData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestPackedExtensions message =
+ TestPackedExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ TestUtil.assertPackedExtensionsSet(message);
+ assertEquals(allPackedExtensionsData, data);
+ }
+
+ public void testCopyFromLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.newBuilder()
+ .mergeFrom(emptyMessageLite).build();
+ assertEquals(emptyMessageLite.toByteString(), emptyMessageLite2.toByteString());
+ }
+
+ public void testMergeFromLite() throws Exception {
+ TestAllTypes message1 = TestAllTypes.newBuilder()
+ .setOptionalInt32(1)
+ .setOptionalString("foo")
+ .addRepeatedString("bar")
+ .setOptionalNestedEnum(TestAllTypes.NestedEnum.BAZ)
+ .build();
+
+ TestAllTypes message2 = TestAllTypes.newBuilder()
+ .setOptionalInt64(2)
+ .setOptionalString("baz")
+ .addRepeatedString("qux")
+ .setOptionalForeignEnum(ForeignEnum.FOREIGN_BAZ)
+ .build();
+
+ ByteString data1 = message1.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data1);
+ ByteString data2 = message2.toByteString();
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data2);
+
+ message1 = TestAllTypes.newBuilder(message1).mergeFrom(message2).build();
+ emptyMessageLite1 = UnittestLite.TestEmptyMessageLite.newBuilder(emptyMessageLite1)
+ .mergeFrom(emptyMessageLite2).build();
+
+ data1 = emptyMessageLite1.toByteString();
+ message2 = TestAllTypes.parseFrom(data1);
+
+ assertEquals(message1, message2);
+ }
+
+ public void testWrongTypeTreatedAsUnknownLite() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllTypes allTypesMessage = TestAllTypes.parseFrom(bizarroData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+ ByteString data = emptyMessageLite.toByteString();
+ TestAllTypes allTypesMessage2 = TestAllTypes.parseFrom(data);
+
+ assertEquals(allTypesMessage.toString(), allTypesMessage2.toString());
+ }
+
+ public void testUnknownExtensionsLite() throws Exception {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ UnittestLite.TestEmptyMessageWithExtensionsLite message =
+ UnittestLite.TestEmptyMessageWithExtensionsLite.parseFrom(allFieldsData);
+
+ assertEquals(allFieldsData, message.toByteString());
+ }
+
+ public void testWrongExtensionTypeTreatedAsUnknownLite() throws Exception {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ ByteString bizarroData = getBizarroData();
+ TestAllExtensions allExtensionsMessage =
+ TestAllExtensions.parseFrom(bizarroData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(bizarroData);
+
+ // All fields should have been interpreted as unknown, so the byte strings
+ // should be the same.
+ assertEquals(emptyMessageLite.toByteString(),
+ allExtensionsMessage.toByteString());
+ }
+
+ public void testParseUnknownEnumValueLite() throws Exception {
+ Descriptors.FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ Descriptors.FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ assertNotNull(singularField);
+ assertNotNull(repeatedField);
+
+ ByteString data =
+ UnknownFieldSet.newBuilder()
+ .addField(singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(5) // not valid
+ .build())
+ .addField(repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(4) // not valid
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(6) // not valid
+ .build())
+ .build()
+ .toByteString();
+
+ UnittestLite.TestEmptyMessageLite emptyMessageLite =
+ UnittestLite.TestEmptyMessageLite.parseFrom(data);
+ data = emptyMessageLite.toByteString();
+
+ {
+ TestAllTypes message = TestAllTypes.parseFrom(data);
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getOptionalNestedEnum());
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getRepeatedNestedEnumList());
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+
+ {
+ TestAllExtensions message =
+ TestAllExtensions.parseFrom(data, TestUtil.getExtensionRegistry());
+ assertEquals(TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(
+ Arrays.asList(TestAllTypes.NestedEnum.FOO, TestAllTypes.NestedEnum.BAZ),
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension));
+ assertEquals(Arrays.asList(5L),
+ message.getUnknownFields()
+ .getField(singularField.getNumber())
+ .getVarintList());
+ assertEquals(Arrays.asList(4L, 6L),
+ message.getUnknownFields()
+ .getField(repeatedField.getNumber())
+ .getVarintList());
+ }
+ }
+
+ public void testClearLite() throws Exception {
+ UnittestLite.TestEmptyMessageLite emptyMessageLite1 =
+ UnittestLite.TestEmptyMessageLite.parseFrom(allFieldsData);
+ UnittestLite.TestEmptyMessageLite emptyMessageLite2 =
+ UnittestLite.TestEmptyMessageLite.newBuilder()
+ .mergeFrom(emptyMessageLite1).clear().build();
+ assertEquals(0, emptyMessageLite2.getSerializedSize());
+ ByteString data = emptyMessageLite2.toByteString();
+ assertEquals(0, data.size());
+ }
+
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
new file mode 100644
index 0000000000..00f201ca58
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java
@@ -0,0 +1,226 @@
+// 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.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link UnmodifiableLazyStringList}.
+ *
+ * @author jonp@google.com (Jon Perlow)
+ */
+public class UnmodifiableLazyStringListTest extends TestCase {
+
+ private static String STRING_A = "A";
+ private static String STRING_B = "B";
+ private static String STRING_C = "C";
+
+ private static ByteString BYTE_STRING_A = ByteString.copyFromUtf8("A");
+ private static ByteString BYTE_STRING_B = ByteString.copyFromUtf8("B");
+ private static ByteString BYTE_STRING_C = ByteString.copyFromUtf8("C");
+
+ public void testReadOnlyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+ assertEquals(3, list.size());
+ assertSame(STRING_A, list.get(0));
+ assertSame(STRING_B, list.get(1));
+ assertSame(STRING_C, list.get(2));
+ assertEquals(BYTE_STRING_A, list.getByteString(0));
+ assertEquals(BYTE_STRING_B, list.getByteString(1));
+ assertEquals(BYTE_STRING_C, list.getByteString(2));
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ assertSame(list.getByteString(0), byteStringList.get(0));
+ assertSame(list.getByteString(1), byteStringList.get(1));
+ assertSame(list.getByteString(2), byteStringList.get(2));
+ }
+
+ public void testModifyMethods() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ try {
+ list.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.add(STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ try {
+ list.set(1, STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ try {
+ byteStringList.remove(0);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+
+ try {
+ byteStringList.add(BYTE_STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+
+ try {
+ byteStringList.set(1, BYTE_STRING_B);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ assertEquals(3, list.size());
+ assertEquals(3, byteStringList.size());
+ }
+
+ public void testIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ Iterator<String> iter = list.iterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ Iterator<ByteString> byteIter = byteStringList.iterator();
+ count = 0;
+ while (byteIter.hasNext()) {
+ byteIter.next();
+ count++;
+ try {
+ byteIter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+ }
+
+ public void testListIterator() {
+ LazyStringArrayList rawList = createSampleList();
+ UnmodifiableLazyStringList list = new UnmodifiableLazyStringList(rawList);
+
+ ListIterator<String> iter = list.listIterator();
+ int count = 0;
+ while (iter.hasNext()) {
+ iter.next();
+ count++;
+ try {
+ iter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.set("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ iter.add("bar");
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+
+ List<ByteString> byteStringList = list.asByteStringList();
+ ListIterator<ByteString> byteIter = byteStringList.listIterator();
+ count = 0;
+ while (byteIter.hasNext()) {
+ byteIter.next();
+ count++;
+ try {
+ byteIter.remove();
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ byteIter.set(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ byteIter.add(BYTE_STRING_A);
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ assertEquals(3, count);
+ }
+
+ private LazyStringArrayList createSampleList() {
+ LazyStringArrayList rawList = new LazyStringArrayList();
+ rawList.add(STRING_A);
+ rawList.add(STRING_B);
+ rawList.add(STRING_C);
+ return rawList;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
new file mode 100644
index 0000000000..982e200f53
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java
@@ -0,0 +1,65 @@
+// 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 com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+import com.google.protobuf.Descriptors.EnumValueDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.test.TestWellKnownTypes;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This test ensures that well-known types are included in protobuf Java
+ * runtime library.
+ */
+public class WellKnownTypesTest extends TestCase {
+ public void testWellKnownTypes() {
+ // The test passes if it compiles.
+ TestWellKnownTypes message = TestWellKnownTypes.newBuilder().build();
+ assertEquals(0, message.getAnyField().getSerializedSize());
+ assertEquals(0, message.getApiField().getSerializedSize());
+ assertEquals(0, message.getDurationField().getSerializedSize());
+ assertEquals(0, message.getEmptyField().getSerializedSize());
+ assertEquals(0, message.getFieldMaskField().getSerializedSize());
+ assertEquals(0, message.getSourceContextField().getSerializedSize());
+ assertEquals(0, message.getStructField().getSerializedSize());
+ assertEquals(0, message.getTimestampField().getSerializedSize());
+ assertEquals(0, message.getTypeField().getSerializedSize());
+ assertEquals(0, message.getInt32Field().getSerializedSize());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WireFormatTest.java b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
new file mode 100644
index 0000000000..370860c2f8
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/java/com/google/protobuf/WireFormatTest.java
@@ -0,0 +1,604 @@
+// 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 com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import protobuf_unittest.UnittestMset.RawMessageSet;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
+import protobuf_unittest.UnittestMset.TestMessageSetExtension2;
+import protobuf_unittest.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestFieldOrderings;
+import protobuf_unittest.UnittestProto.TestOneof2;
+import protobuf_unittest.UnittestProto.TestOneofBackwardsCompatible;
+import protobuf_unittest.UnittestProto.TestPackedExtensions;
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import proto2_wireformat_unittest.UnittestMsetWireFormat.TestMessageSet;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import junit.framework.TestCase;
+
+/**
+ * Tests related to parsing and serialization.
+ *
+ * @author kenton@google.com (Kenton Varda)
+ */
+public class WireFormatTest extends TestCase {
+ public void testSerialization() throws Exception {
+ TestAllTypes message = TestUtil.getAllSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializationPacked() throws Exception {
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(rawBytes);
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testSerializeExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensions message = TestUtil.getAllExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensions() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
+ public void testSerializationPackedWithoutGetSerializedSize()
+ throws Exception {
+ // Write directly to an OutputStream, without invoking getSerializedSize()
+ // This used to be a bug where the size of a packed field was incorrect,
+ // since getSerializedSize() was never invoked.
+ TestPackedTypes message = TestUtil.getPackedSet();
+
+ // Directly construct a CodedOutputStream around the actual OutputStream,
+ // in case writeTo(OutputStream output) invokes getSerializedSize();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(outputStream);
+
+ message.writeTo(codedOutput);
+
+ codedOutput.flush();
+
+ TestPackedTypes message2 = TestPackedTypes.parseFrom(
+ outputStream.toByteArray());
+
+ TestUtil.assertPackedFieldsSet(message2);
+ }
+
+ public void testSerializeExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestAllTypes message2 = TestAllTypes.parseFrom(rawBytes);
+
+ TestUtil.assertAllFieldsSet(message2);
+ }
+
+ public void testSerializePackedExtensionsLite() throws Exception {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ TestPackedTypes message2 = TestUtil.getPackedSet();
+ ByteString rawBytes2 = message2.toByteString();
+
+ assertEquals(rawBytes, rawBytes2);
+ }
+
+ public void testParseExtensions() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensions message2 =
+ TestAllExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message2);
+ }
+
+ public void testParsePackedExtensions() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions message = TestUtil.getPackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestPackedExtensions message2 =
+ TestPackedExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ public void testParseExtensionsLite() throws Exception {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes message = TestUtil.getAllSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry_lite = TestUtilLite.getExtensionRegistryLite();
+
+ TestAllExtensionsLite message2 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry_lite);
+
+ TestUtil.assertAllExtensionsSet(message2);
+
+ // Try again using a full extension registry.
+ ExtensionRegistry registry = TestUtil.getExtensionRegistry();
+
+ TestAllExtensionsLite message3 =
+ TestAllExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertAllExtensionsSet(message3);
+ }
+
+ public void testParsePackedExtensionsLite() throws Exception {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensionsLite message = TestUtilLite.getLitePackedExtensionsSet();
+ ByteString rawBytes = message.toByteString();
+
+ ExtensionRegistryLite registry = TestUtilLite.getExtensionRegistryLite();
+
+ TestPackedExtensionsLite message2 =
+ TestPackedExtensionsLite.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ public void testExtensionsSerializedSize() throws Exception {
+ assertNotSame(TestUtil.getAllSet().getSerializedSize(),
+ TestUtil.getAllExtensionsSet().getSerializedSize());
+ }
+
+ public void testSerializeDelimited() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ TestUtil.getAllSet().writeDelimitedTo(output);
+ output.write(12);
+ TestUtil.getPackedSet().writeDelimitedTo(output);
+ output.write(34);
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+
+ TestUtil.assertAllFieldsSet(TestAllTypes.parseDelimitedFrom(input));
+ assertEquals(12, input.read());
+ TestUtil.assertPackedFieldsSet(TestPackedTypes.parseDelimitedFrom(input));
+ assertEquals(34, input.read());
+ assertEquals(-1, input.read());
+
+ // We're at EOF, so parsing again should return null.
+ assertTrue(TestAllTypes.parseDelimitedFrom(input) == null);
+ }
+
+ private void assertFieldsInOrder(ByteString data) throws Exception {
+ CodedInputStream input = data.newCodedInput();
+ int previousTag = 0;
+
+ while (true) {
+ int tag = input.readTag();
+ if (tag == 0) {
+ break;
+ }
+
+ assertTrue(tag > previousTag);
+ previousTag = tag;
+ input.skipField(tag);
+ }
+ }
+
+ public void testInterleavedFieldsAndExtensions() throws Exception {
+ // Tests that fields are written in order even when extension ranges
+ // are interleaved with field numbers.
+ ByteString data =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build().toByteString();
+ assertFieldsInOrder(data);
+
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ ByteString dynamic_data =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build().toByteString();
+ assertFieldsInOrder(dynamic_data);
+ }
+
+ private ExtensionRegistry getTestFieldOrderingsRegistry() {
+ ExtensionRegistry result = ExtensionRegistry.newInstance();
+ result.add(UnittestProto.myExtensionInt);
+ result.add(UnittestProto.myExtensionString);
+ return result;
+ }
+
+ public void testParseMultipleExtensionRanges() throws Exception {
+ // Make sure we can parse a message that contains multiple extensions
+ // ranges.
+ TestFieldOrderings source =
+ TestFieldOrderings.newBuilder()
+ .setMyInt(1)
+ .setMyString("foo")
+ .setMyFloat(1.0F)
+ .setExtension(UnittestProto.myExtensionInt, 23)
+ .setExtension(UnittestProto.myExtensionString, "bar")
+ .build();
+ TestFieldOrderings dest =
+ TestFieldOrderings.parseFrom(source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ public void testParseMultipleExtensionRangesDynamic() throws Exception {
+ // Same as above except with DynamicMessage.
+ Descriptors.Descriptor descriptor = TestFieldOrderings.getDescriptor();
+ DynamicMessage source =
+ DynamicMessage.newBuilder(TestFieldOrderings.getDescriptor())
+ .setField(descriptor.findFieldByName("my_int"), 1L)
+ .setField(descriptor.findFieldByName("my_string"), "foo")
+ .setField(descriptor.findFieldByName("my_float"), 1.0F)
+ .setField(UnittestProto.myExtensionInt.getDescriptor(), 23)
+ .setField(UnittestProto.myExtensionString.getDescriptor(), "bar")
+ .build();
+ DynamicMessage dest =
+ DynamicMessage.parseFrom(descriptor, source.toByteString(),
+ getTestFieldOrderingsRegistry());
+ assertEquals(source, dest);
+ }
+
+ private static final int UNKNOWN_TYPE_ID = 1550055;
+ private static final int TYPE_ID_1 =
+ TestMessageSetExtension1.getDescriptor().getExtensions().get(0).getNumber();
+ private static final int TYPE_ID_2 =
+ TestMessageSetExtension2.getDescriptor().getExtensions().get(0).getNumber();
+
+ public void testSerializeMessageSetEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(true);
+ }
+
+ public void testSerializeMessageSetNotEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(false);
+ }
+
+ private void testSerializeMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ // Set up a TestMessageSet with two known messages and an unknown one.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder()
+ .setExtension(
+ TestMessageSetExtension1.messageSetExtension,
+ TestMessageSetExtension1.newBuilder().setI(123).build())
+ .setExtension(
+ TestMessageSetExtension2.messageSetExtension,
+ TestMessageSetExtension2.newBuilder().setStr("foo").build())
+ .setUnknownFields(
+ UnknownFieldSet.newBuilder()
+ .addField(UNKNOWN_TYPE_ID,
+ UnknownFieldSet.Field.newBuilder()
+ .addLengthDelimited(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build())
+ .build();
+
+ ByteString data = messageSet.toByteString();
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet raw = RawMessageSet.parseFrom(data);
+
+ assertTrue(raw.getUnknownFields().asMap().isEmpty());
+
+ assertEquals(3, raw.getItemCount());
+ assertEquals(TYPE_ID_1, raw.getItem(0).getTypeId());
+ assertEquals(TYPE_ID_2, raw.getItem(1).getTypeId());
+ assertEquals(UNKNOWN_TYPE_ID, raw.getItem(2).getTypeId());
+
+ TestMessageSetExtension1 message1 =
+ TestMessageSetExtension1.parseFrom(
+ raw.getItem(0).getMessage().toByteArray());
+ assertEquals(123, message1.getI());
+
+ TestMessageSetExtension2 message2 =
+ TestMessageSetExtension2.parseFrom(
+ raw.getItem(1).getMessage().toByteArray());
+ assertEquals("foo", message2.getStr());
+
+ assertEquals("bar", raw.getItem(2).getMessage().toStringUtf8());
+ }
+
+ public void testParseMessageSetEagerly() throws Exception {
+ testParseMessageSetWithFlag(true);
+ }
+
+ public void testParseMessageSetNotEagerly()throws Exception {
+ testParseMessageSetWithFlag(false);
+ }
+
+ private void testParseMessageSetWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+ extensionRegistry.add(TestMessageSetExtension2.messageSetExtension);
+
+ // Set up a RawMessageSet with two known messages and an unknown one.
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_2)
+ .setMessage(
+ TestMessageSetExtension2.newBuilder()
+ .setStr("foo")
+ .build().toByteString())
+ .build())
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(UNKNOWN_TYPE_ID)
+ .setMessage(ByteString.copyFromUtf8("bar"))
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ assertEquals("foo", messageSet.getExtension(
+ TestMessageSetExtension2.messageSetExtension).getStr());
+
+ // Check for unknown field with type LENGTH_DELIMITED,
+ // number UNKNOWN_TYPE_ID, and contents "bar".
+ UnknownFieldSet unknownFields = messageSet.getUnknownFields();
+ assertEquals(1, unknownFields.asMap().size());
+ assertTrue(unknownFields.hasField(UNKNOWN_TYPE_ID));
+
+ UnknownFieldSet.Field field = unknownFields.getField(UNKNOWN_TYPE_ID);
+ assertEquals(1, field.getLengthDelimitedList().size());
+ assertEquals("bar", field.getLengthDelimitedList().get(0).toStringUtf8());
+ }
+
+ public void testParseMessageSetExtensionEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(true);
+ }
+
+ public void testParseMessageSetExtensionNotEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(false);
+ }
+
+ private void testParseMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeLazyMessageSetExtensionEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeLazyMessageSetExtensionNotEagerly() throws Exception {
+ testMergeLazyMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeLazyMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ ByteString data = raw.toByteString();
+
+ // Parse as a TestMessageSet and store value into lazy field
+ TestMessageSet messageSet =
+ TestMessageSet.parseFrom(data, extensionRegistry);
+ // Merge lazy field check the contents.
+ messageSet =
+ messageSet.toBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ public void testMergeMessageSetExtensionEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(true);
+ }
+
+ public void testMergeMessageSetExtensionNotEagerly() throws Exception {
+ testMergeMessageSetExtensionWithFlag(false);
+ }
+
+ private void testMergeMessageSetExtensionWithFlag(boolean eagerParsing)
+ throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistry extensionRegistry = ExtensionRegistry.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int TYPE_ID_1 =
+ TestMessageSetExtension1
+ .getDescriptor().getExtensions().get(0).getNumber();
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(TYPE_ID_1)
+ .setMessage(
+ TestMessageSetExtension1.newBuilder()
+ .setI(123)
+ .build().toByteString())
+ .build())
+ .build();
+
+ // Serialize RawMessageSet unnormally (message value before type id)
+ ByteString.CodedBuilder out = ByteString.newCodedBuilder(
+ raw.getSerializedSize());
+ CodedOutputStream output = out.getCodedOutput();
+ List<RawMessageSet.Item> items = raw.getItemList();
+ for (int i = 0; i < items.size(); i++) {
+ RawMessageSet.Item item = items.get(i);
+ output.writeTag(1, WireFormat.WIRETYPE_START_GROUP);
+ output.writeBytes(3, item.getMessage());
+ output.writeInt32(2, item.getTypeId());
+ output.writeTag(1, WireFormat.WIRETYPE_END_GROUP);
+ }
+ ByteString data = out.build();
+
+ // Merge bytes into TestMessageSet and check the contents.
+ TestMessageSet messageSet =
+ TestMessageSet.newBuilder().mergeFrom(data, extensionRegistry).build();
+ assertEquals(123, messageSet.getExtension(
+ TestMessageSetExtension1.messageSetExtension).getI());
+ }
+
+ // ================================================================
+ // oneof
+ public void testOneofWireFormat() throws Exception {
+ TestOneof2.Builder builder = TestOneof2.newBuilder();
+ TestUtil.setOneof(builder);
+ TestOneof2 message = builder.build();
+ ByteString rawBytes = message.toByteString();
+
+ assertEquals(rawBytes.size(), message.getSerializedSize());
+
+ TestOneof2 message2 = TestOneof2.parseFrom(rawBytes);
+ TestUtil.assertOneofSet(message2);
+ }
+
+ public void testOneofOnlyLastSet() throws Exception {
+ TestOneofBackwardsCompatible source = TestOneofBackwardsCompatible
+ .newBuilder().setFooInt(100).setFooString("101").build();
+
+ ByteString rawBytes = source.toByteString();
+ TestOneof2 message = TestOneof2.parseFrom(rawBytes);
+ assertFalse(message.hasFooInt());
+ assertTrue(message.hasFooString());
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/any_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/any_test.proto
new file mode 100644
index 0000000000..80173d8a0e
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/any_test.proto
@@ -0,0 +1,42 @@
+// 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.
+
+syntax = "proto3";
+
+package any_test;
+
+option java_package = "any_test";
+option java_outer_classname = "AnyTestProto";
+
+import "google/protobuf/any.proto";
+
+message TestAny {
+ google.protobuf.Any value = 1;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto
new file mode 100644
index 0000000000..2367bd8bd0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/field_presence_test.proto
@@ -0,0 +1,94 @@
+// 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.
+
+syntax = "proto3";
+
+package field_presence_test;
+
+import "google/protobuf/unittest.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "FieldPresenceTestProto";
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ message NestedMessage {
+ int32 value = 1;
+ }
+
+ int32 optional_int32 = 1;
+ string optional_string = 2;
+ bytes optional_bytes = 3;
+ NestedEnum optional_nested_enum = 4;
+ NestedMessage optional_nested_message = 5;
+ protobuf_unittest.TestRequired optional_proto2_message = 6;
+ NestedMessage optional_lazy_message = 7 [lazy=true];
+
+ oneof oneof_field {
+ int32 oneof_int32 = 11;
+ uint32 oneof_uint32 = 12;
+ string oneof_string = 13;
+ bytes oneof_bytes = 14;
+ NestedEnum oneof_nested_enum = 15;
+ NestedMessage oneof_nested_message = 16;
+ protobuf_unittest.TestRequired oneof_proto2_message = 17;
+ }
+
+ repeated int32 repeated_int32 = 21;
+ repeated string repeated_string = 22;
+ repeated bytes repeated_bytes = 23;
+ repeated NestedEnum repeated_nested_enum = 24;
+ repeated NestedMessage repeated_nested_message = 25;
+ repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+ repeated NestedEnum packed_nested_enum = 27 [packed = true];
+}
+
+message TestOptionalFieldsOnly {
+ int32 optional_int32 = 1;
+ string optional_string = 2;
+ bytes optional_bytes = 3;
+ TestAllTypes.NestedEnum optional_nested_enum = 4;
+ TestAllTypes.NestedMessage optional_nested_message = 5;
+ protobuf_unittest.TestRequired optional_proto2_message = 6;
+ TestAllTypes.NestedMessage optional_lazy_message = 7 [lazy=true];
+}
+
+message TestRepeatedFieldsOnly {
+ repeated int32 repeated_int32 = 21;
+ repeated string repeated_string = 22;
+ repeated bytes repeated_bytes = 23;
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 24;
+ repeated TestAllTypes.NestedMessage repeated_nested_message = 25;
+ repeated protobuf_unittest.TestRequired repeated_proto2_message = 26;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
new file mode 100644
index 0000000000..5580f72d99
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto
@@ -0,0 +1,71 @@
+// 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.
+
+// Author: Naoki Iwasaki (niwasaki@google.com)
+//
+// A proto file with lazy fields
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message LazyMessageLite {
+ optional int32 num = 1;
+ optional int32 num_with_default = 2 [default = 421];
+ optional LazyInnerMessageLite inner = 3 [lazy = true];
+ repeated LazyInnerMessageLite repeated_inner = 4 [lazy = true];
+
+ oneof oneof_field {
+ int32 oneof_num = 5;
+ LazyInnerMessageLite oneof_inner = 6 [lazy = true];
+ }
+}
+
+message LazyInnerMessageLite {
+ optional int32 num = 1;
+ optional int32 num_with_default = 2 [default = 42];
+ optional LazyNestedInnerMessageLite nested = 3 [lazy = true];
+
+ extensions 1000 to max;
+}
+
+message LazyExtension {
+ extend LazyInnerMessageLite {
+ optional LazyExtension extension = 1000;
+ }
+ optional string name = 1;
+}
+
+message LazyNestedInnerMessageLite {
+ optional int32 num = 1;
+ optional int32 num_with_default = 2 [default = 4];
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
new file mode 100644
index 0000000000..6eef42c578
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto
@@ -0,0 +1,81 @@
+// 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.
+
+// Author: pbogle@google.com (Phil Bogle)
+
+syntax = "proto2";
+
+package protobuf_unittest.lite_equals_and_hash;
+
+option optimize_for = LITE_RUNTIME;
+
+message TestOneofEquals {
+ oneof oneof_field {
+ string name = 1;
+ int32 value = 2;
+ }
+}
+
+message Foo {
+ optional int32 value = 1;
+ repeated Bar bar = 2;
+
+ extensions 100 to max;
+}
+
+message Bar {
+ extend Foo {
+ optional Bar foo_ext = 100;
+ }
+
+ optional string name = 1;
+}
+
+message BarPrime {
+ optional string name = 1;
+}
+
+message Empty {
+}
+
+extend Foo {
+ optional int32 varint = 101;
+ optional fixed32 fixed32 = 102;
+ optional fixed64 fixed64 = 103;
+ optional group MyGroup = 104 {
+ optional string group_value = 1;
+ }
+}
+
+message TestRecursiveOneof {
+ oneof Foo {
+ TestRecursiveOneof r = 1;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
new file mode 100644
index 0000000000..2ca0251ca2
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -0,0 +1,121 @@
+// 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.
+
+syntax = "proto2";
+
+
+option java_outer_classname = "MapForProto2TestProto";
+
+message TestMap {
+ message MessageValue {
+ optional int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+
+ message MessageWithRequiredFields {
+ required int32 value = 1;
+ }
+ map<int32, MessageWithRequiredFields> required_message_map = 11;
+}
+
+message TestUnknownEnumValue {
+ // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+ // parsing behavior of TestMap regarding unknown enum values.
+ map<int32, int32> int32_to_int32_field = 4;
+}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+ optional int32 value = 1;
+ map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
+
+
+// a decoy of TestMap for testing parsing errors
+message BizarroTestMap {
+ map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
+ map<string, int32> int32_to_string_field = 2; // different key and value types
+ map<string, int32> int32_to_bytes_field = 3; // different key types, same value
+ map<string, bytes> int32_to_enum_field = 4; // different key and value types
+ map<string, bytes> int32_to_message_field = 5; // different key and value types
+ map<string, bytes> string_to_int32_field = 6; // same key type, different value
+}
+
+// Used to test that java reserved words can be used as protobuf field names
+// Not all reserved words are tested (to avoid bloat) but instead an arbitrary
+// subset of them chosen to cover various keyword categories like
+// type, modifier, declaration, etc.
+message ReservedAsMapField {
+ map<string, uint32> if = 1;
+ map<string, uint32> const = 2;
+ map<string, uint32> private = 3;
+ map<string, uint32> class = 4;
+ map<string, uint32> int = 5;
+ map<string, uint32> void = 6;
+ map<string, uint32> string = 7; // These are also proto keywords
+ map<string, uint32> package = 8;
+ map<string, uint32> enum = 9; // Most recent Java reserved word
+ map<string, uint32> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
+
+message ReservedAsMapFieldWithEnumValue {
+ enum SampleEnum {
+ A = 0;
+ B = 1;
+ }
+ map<string, SampleEnum> if = 1;
+ map<string, SampleEnum> const = 2;
+ map<string, SampleEnum> private = 3;
+ map<string, SampleEnum> class = 4;
+ map<string, SampleEnum> int = 5;
+ map<string, SampleEnum> void = 6;
+ map<string, SampleEnum> string = 7; // These are also proto keywords
+ map<string, SampleEnum> package = 8;
+ map<string, SampleEnum> enum = 9; // Most recent Java reserved word
+ map<string, SampleEnum> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
+package map_for_proto2_lite_test;
+option java_package = "map_lite_test";
+option optimize_for = LITE_RUNTIME;
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto
new file mode 100644
index 0000000000..974f8a2c74
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto
@@ -0,0 +1,120 @@
+// 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.
+
+syntax = "proto2";
+
+package map_for_proto2_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapForProto2TestProto";
+
+message TestMap {
+ message MessageValue {
+ optional int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+
+ message MessageWithRequiredFields {
+ required int32 value = 1;
+ }
+ map<int32, MessageWithRequiredFields> required_message_map = 11;
+}
+
+message TestUnknownEnumValue {
+ // Wire-compatible with TestMap.int32_to_enum_field so we can test the
+ // parsing behavior of TestMap regarding unknown enum values.
+ map<int32, int32> int32_to_int32_field = 4;
+}
+
+// Test that the maps initialization code works correctly when the map field
+// references the containing message.
+message TestRecursiveMap {
+ optional int32 value = 1;
+ map<int32, TestRecursiveMap> recursive_map_field = 2;
+}
+
+
+// a decoy of TestMap for testing parsing errors
+message BizarroTestMap {
+ map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
+ map<string, int32> int32_to_string_field = 2; // different key and value types
+ map<string, int32> int32_to_bytes_field = 3; // different key types, same value
+ map<string, bytes> int32_to_enum_field = 4; // different key and value types
+ map<string, bytes> int32_to_message_field = 5; // different key and value types
+ map<string, bytes> string_to_int32_field = 6; // same key type, different value
+}
+
+// Used to test that java reserved words can be used as protobuf field names
+// Not all reserved words are tested (to avoid bloat) but instead an arbitrary
+// subset of them chosen to cover various keyword categories like
+// type, modifier, declaration, etc.
+message ReservedAsMapField {
+ map<string, uint32> if = 1;
+ map<string, uint32> const = 2;
+ map<string, uint32> private = 3;
+ map<string, uint32> class = 4;
+ map<string, uint32> int = 5;
+ map<string, uint32> void = 6;
+ map<string, uint32> string = 7; // These are also proto keywords
+ map<string, uint32> package = 8;
+ map<string, uint32> enum = 9; // Most recent Java reserved word
+ map<string, uint32> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
+
+message ReservedAsMapFieldWithEnumValue {
+ enum SampleEnum {
+ A = 0;
+ B = 1;
+ }
+ map<string, SampleEnum> if = 1;
+ map<string, SampleEnum> const = 2;
+ map<string, SampleEnum> private = 3;
+ map<string, SampleEnum> class = 4;
+ map<string, SampleEnum> int = 5;
+ map<string, SampleEnum> void = 6;
+ map<string, SampleEnum> string = 7; // These are also proto keywords
+ map<string, SampleEnum> package = 8;
+ map<string, SampleEnum> enum = 9; // Most recent Java reserved word
+ map<string, SampleEnum> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto
new file mode 100644
index 0000000000..b02ac599a5
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto
@@ -0,0 +1,61 @@
+// 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.
+
+// Regression test for a map initilaization order bug. The bug only manifests
+// when:
+// 1. A message contains map fields and is also extendable.
+// 2. There is a file-level extension defined in the same file referencing
+// the above message as the extension type.
+// 3. The program executes in the following order:
+// a. getDescriptor() is called on another message in the same file.
+// b. use protobuf reflection to access the map field.
+// The symptom is a NullPointerException being thrown.
+syntax = "proto2";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapInitializationOrderTest";
+option java_multiple_files = true;
+
+// Mirrors the structure of
+// javatests/com/google/cloud/common/logging/logging_test.proto.
+
+message Message1 {
+ map<string, bool> map_field = 1;
+ extensions 1000 to max;
+}
+
+extend Message1 {
+ optional Message1 recursive_extension = 1001;
+}
+
+message RedactAllTypes {
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_test.proto
new file mode 100644
index 0000000000..bc2105e50f
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/map_test.proto
@@ -0,0 +1,110 @@
+// 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.
+
+syntax = "proto3";
+
+package map_test;
+
+option java_package = "map_test";
+option java_outer_classname = "MapTestProto";
+
+message TestMap {
+ message MessageValue {
+ int32 value = 1;
+ }
+ enum EnumValue {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ QUX = 3;
+ }
+
+ map<int32, int32> int32_to_int32_field = 1;
+ map<int32, string> int32_to_string_field = 2;
+ map<int32, bytes> int32_to_bytes_field = 3;
+ map<int32, EnumValue> int32_to_enum_field = 4;
+ map<int32, MessageValue> int32_to_message_field = 5;
+ map<string, int32> string_to_int32_field = 6;
+ map<uint32, int32> uint32_to_int32_field = 7;
+ map<int64, int32> int64_to_int32_field = 8;
+}
+
+// Used to test that a nested builder containing map fields will properly
+// propagate the onChange event and mark its parent dirty when a change
+// is made to a map field.
+message TestOnChangeEventPropagation {
+ TestMap optional_message = 1;
+}
+
+// a decoy of TestMap for testing parsing errors
+message BizarroTestMap {
+ map<int32, bytes> int32_to_int32_field = 1; // same key type, different value
+ map<string, int32> int32_to_string_field = 2; // different key and value types
+ map<string, int32> int32_to_bytes_field = 3; // different key types, same value
+ map<string, bytes> int32_to_enum_field = 4; // different key and value types
+ map<string, bytes> int32_to_message_field = 5; // different key and value types
+ map<string, bytes> string_to_int32_field = 6; // same key type, different value
+}
+
+// Used to test that java reserved words can be used as protobuf field names
+// Not all reserved words are tested (to avoid bloat) but instead an arbitrary
+// subset of them chosen to cover various keyword categories like
+// type, modifier, declaration, etc.
+message ReservedAsMapField {
+ map<string, uint32> if = 1;
+ map<string, uint32> const = 2;
+ map<string, uint32> private = 3;
+ map<string, uint32> class = 4;
+ map<string, uint32> int = 5;
+ map<string, uint32> void = 6;
+ map<string, uint32> string = 7; // These are also proto keywords
+ map<string, uint32> package = 8;
+ map<string, uint32> enum = 9; // Most recent Java reserved word
+ map<string, uint32> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
+
+message ReservedAsMapFieldWithEnumValue {
+ enum SampleEnum {
+ A = 0;
+ B = 1;
+ }
+ map<string, SampleEnum> if = 1;
+ map<string, SampleEnum> const = 2;
+ map<string, SampleEnum> private = 3;
+ map<string, SampleEnum> class = 4;
+ map<string, SampleEnum> int = 5;
+ map<string, SampleEnum> void = 6;
+ map<string, SampleEnum> string = 7; // These are also proto keywords
+ map<string, SampleEnum> package = 8;
+ map<string, SampleEnum> enum = 9; // Most recent Java reserved word
+ map<string, SampleEnum> null = 10;
+ // null is not a 'reserved word' per se but as a literal needs similar care
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
new file mode 100644
index 0000000000..92790506f0
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
@@ -0,0 +1,78 @@
+// 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.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// A proto file which tests the java_multiple_files option.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+import "google/protobuf/unittest.proto";
+import "google/protobuf/descriptor.proto";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "MultipleFilesTestProto";
+
+
+message MessageWithNoOuter {
+ message NestedMessage {
+ optional int32 i = 1;
+ }
+ enum NestedEnum {
+ BAZ = 3;
+ }
+ optional NestedMessage nested = 1;
+ repeated TestAllTypes foreign = 2;
+ optional NestedEnum nested_enum = 3;
+ optional EnumWithNoOuter foreign_enum = 4;
+}
+
+extend google.protobuf.EnumValueOptions {
+ optional int32 enum_value_option = 7654321;
+}
+
+enum EnumWithNoOuter {
+ FOO = 1 [(enum_value_option) = 12345];
+ BAR = 2;
+}
+
+service ServiceWithNoOuter {
+ rpc Foo(MessageWithNoOuter) returns(TestAllTypes);
+}
+
+extend TestAllExtensions {
+ optional int32 extension_with_outer = 1234567;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto
new file mode 100644
index 0000000000..a5dd66d889
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto
@@ -0,0 +1,54 @@
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+//
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option java_multiple_files = true;
+option java_outer_classname = "NestedBuilders";
+
+
+message Vehicle {
+ optional Engine engine = 1;
+ repeated Wheel wheel = 2;
+}
+
+message Engine {
+ optional int32 cylinder = 1;
+ optional int32 liters = 2;
+}
+
+message Wheel {
+ optional int32 radius = 1;
+ optional int32 width = 2;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
new file mode 100644
index 0000000000..704e649e02
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
@@ -0,0 +1,47 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions. Note that this must be defined in
+// a separate file to properly test the initialization of the outer class.
+
+syntax = "proto2";
+
+import "com/google/protobuf/non_nested_extension.proto";
+
+package protobuf_unittest;
+
+
+message MyNestedExtension {
+ extend MessageToBeExtended {
+ optional MessageToBeExtended recursiveExtension = 2;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
new file mode 100644
index 0000000000..a95c38b234
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
@@ -0,0 +1,49 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with nested extensions for a MessageLite messages. Note that
+// this must be defined in a separate file to properly test the initialization
+// of the outer class.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+import "com/google/protobuf/non_nested_extension_lite.proto";
+
+message MyNestedExtensionLite {
+ extend MessageLiteToBeExtended {
+ optional MessageLiteToBeExtended recursiveExtensionLite = 3;
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto
new file mode 100644
index 0000000000..31fac55295
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto
@@ -0,0 +1,50 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message MessageToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtension {
+}
+
+extend MessageToBeExtended {
+ optional MyNonNestedExtension nonNestedExtension = 1;
+}
+
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
new file mode 100644
index 0000000000..37c369edaa
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+//
+// A proto file with extensions for a MessageLite messages.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = LITE_RUNTIME;
+
+message MessageLiteToBeExtended {
+ extensions 1 to max;
+}
+
+message MyNonNestedExtensionLite {
+}
+
+extend MessageLiteToBeExtended {
+ optional MyNonNestedExtensionLite nonNestedExtensionLite = 1;
+}
+
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto
new file mode 100644
index 0000000000..4208368146
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto
@@ -0,0 +1,40 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+// This message's name is the same with the default outer class name of this
+// proto file. It's used to test if the compiler can avoid this conflict
+// correctly.
+message OuterClassNameTest {
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto
new file mode 100644
index 0000000000..3e5956b0d4
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto
@@ -0,0 +1,44 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message TestMessage2 {
+ message NestedMessage {
+ // This message's name is the same with the default outer class name of this
+ // proto file. It's used to test if the compiler can avoid this conflict
+ // correctly.
+ message OuterClassNameTest2 {
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto
new file mode 100644
index 0000000000..74a8ba3c3d
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto
@@ -0,0 +1,45 @@
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message TestMessage3 {
+ message NestedMessage {
+ // This enum's name is the same with the default outer class name of this
+ // proto file. It's used to test if the compiler can avoid this conflict
+ // correctly.
+ enum OuterClassNameTest3 {
+ DUMMY_VALUE = 1;
+ }
+ }
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
new file mode 100644
index 0000000000..d2c77936c3
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
@@ -0,0 +1,168 @@
+// 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.
+
+// Author: jonp@google.com (Jon Perlow)
+
+// This file tests that various identifiers work as field and type names even
+// though the same identifiers are used internally by the java code generator.
+
+syntax = "proto2";
+
+// Some generic_services option(s) added automatically.
+// See: http://go/proto2-generic-services-default
+option java_generic_services = true; // auto-added
+
+package io_protocol_tests;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TestBadIdentifiersProto";
+
+message TestMessage {
+ optional string cached_size = 1;
+ optional string serialized_size = 2;
+ optional string class = 3;
+}
+
+message Descriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ message NestedDescriptor {
+ option no_standard_descriptor_accessor = true;
+ optional string descriptor = 1;
+ }
+ optional NestedDescriptor nested_descriptor = 2;
+ enum NestedEnum {
+ UNKNOWN = 0;
+ FOO = 1;
+ }
+}
+
+message Parser {
+ enum ParserEnum {
+ UNKNOWN = 0;
+ PARSER = 1;
+ }
+ optional ParserEnum parser = 1;
+}
+
+message Deprecated {
+ enum TestEnum {
+ UNKNOWN = 0;
+ FOO = 1;
+
+ // Test if @Deprecated annotation conflicts with Deprecated message name.
+ BAR = 2 [ deprecated = true ];
+ }
+
+ optional int32 field1 = 1 [deprecated=true];
+ optional TestEnum field2 = 2 [deprecated=true];
+ optional TestMessage field3 = 3 [deprecated=true];
+}
+
+message Override {
+ optional int32 override = 1;
+}
+
+message Object {
+ optional int32 object = 1;
+ optional string string_object = 2;
+}
+
+message String {
+ optional string string = 1;
+}
+
+message Integer {
+ optional int32 integer = 1;
+}
+
+message Long {
+ optional int32 long = 1;
+}
+
+message Float {
+ optional float float = 1;
+}
+
+message Double {
+ optional double double = 1;
+}
+
+service TestConflictingMethodNames {
+ rpc Override(TestMessage) returns (TestMessage);
+}
+
+message TestConflictingFieldNames {
+ enum TestEnum {
+ UNKNOWN = 0;
+ FOO = 1;
+ }
+ message TestMessage {
+ }
+ repeated int32 int32_field = 1;
+ repeated TestEnum enum_field = 2;
+ repeated string string_field = 3;
+ repeated bytes bytes_field = 4;
+ repeated TestMessage message_field = 5;
+
+ optional int32 int32_field_count = 11;
+ optional TestEnum enum_field_count = 12;
+ optional string string_field_count = 13;
+ optional bytes bytes_field_count = 14;
+ optional TestMessage message_field_count = 15;
+
+ repeated int32 Int32Field = 21; // NO_PROTO3
+ repeated TestEnum EnumField = 22; // NO_PROTO3
+ repeated string StringField = 23; // NO_PROTO3
+ repeated bytes BytesField = 24; // NO_PROTO3
+ repeated TestMessage MessageField = 25; // NO_PROTO3
+
+ // This field conflicts with "int32_field" as they both generate
+ // the method getInt32FieldList().
+ required int32 int32_field_list = 31; // NO_PROTO3
+
+ extensions 1000 to max; // NO_PROTO3
+
+ repeated int64 int64_field = 41;
+ extend TestConflictingFieldNames { // NO_PROTO3
+ // We don't generate accessors for extensions so the following extension
+ // fields don't conflict with the repeated field "int64_field".
+ optional int64 int64_field_count = 1001; // NO_PROTO3
+ optional int64 int64_field_list = 1002; // NO_PROTO3
+ } // NO_PROTO3
+}
+
+message TestMapField {
+ message MapField {}
+ message Pair {}
+ message Message {}
+
+ map<int32, int32> map_field = 1;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto
new file mode 100644
index 0000000000..119c1dcbad
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto
@@ -0,0 +1,51 @@
+// 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.
+
+// Author: Jacob Butcher (jbaum@google.com)
+//
+// Test file option java_string_check_utf8.
+syntax = "proto2";
+
+package proto2_test_check_utf8;
+
+option java_outer_classname = "TestCheckUtf8";
+option java_string_check_utf8 = true;
+
+message StringWrapper {
+ required string req = 1;
+ optional string opt = 2;
+ repeated string rep = 3;
+}
+
+message BytesWrapper {
+ required bytes req = 1;
+ optional bytes opt = 2;
+ repeated bytes rep = 3;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto
new file mode 100644
index 0000000000..f06d76d629
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto
@@ -0,0 +1,52 @@
+// 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.
+
+// Author: Jacob Butcher (jbaum@google.com)
+//
+// Test file option java_string_check_utf8.
+syntax = "proto2";
+
+package proto2_test_check_utf8_size;
+
+option java_outer_classname = "TestCheckUtf8Size";
+option java_string_check_utf8 = true;
+option optimize_for = CODE_SIZE;
+
+message StringWrapperSize {
+ required string req = 1;
+ optional string opt = 2;
+ repeated string rep = 3;
+}
+
+message BytesWrapperSize {
+ required bytes req = 1;
+ optional bytes opt = 2;
+ repeated bytes rep = 3;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto
new file mode 100644
index 0000000000..f8efd455a1
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_custom_options.proto
@@ -0,0 +1,44 @@
+// 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.
+
+// Author: Feng Xiao (xiaofeng@google.com)
+//
+// Test that custom options defined in a proto file's dependencies are properly
+// initialized.
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+import "google/protobuf/unittest_custom_options.proto";
+
+message TestMessageWithCustomOptionsContainer {
+ optional TestMessageWithCustomOptions field = 1;
+}
diff --git a/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
new file mode 100644
index 0000000000..645f57b4bb
--- /dev/null
+++ b/third_party/protobuf/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
@@ -0,0 +1,61 @@
+// 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.
+
+// Author: Darick Tong (darick@google.com)
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message Proto1 {
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasBoolValue";
+
+ option experimental_java_interface_extends =
+ "com.google.protobuf.ExtraInterfaces.HasByteValue";
+
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
+
+ option experimental_java_builder_interface =
+ "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder"
+ "<Proto1, Builder>";
+
+ optional string string_value = 1;
+ optional bool bool_value = 2;
+ optional bytes byte_value = 3;
+ optional int32 int_value = 4;
+}
+
+message Proto2 {
+ option experimental_java_message_interface =
+ "com.google.protobuf.ExtraInterfaces.HasBoolValue";
+
+ optional bool bool_value = 1;
+}
diff --git a/third_party/protobuf/java/lite/generate-sources-build.xml b/third_party/protobuf/java/lite/generate-sources-build.xml
new file mode 100644
index 0000000000..89c21c1315
--- /dev/null
+++ b/third_party/protobuf/java/lite/generate-sources-build.xml
@@ -0,0 +1,20 @@
+<project name="generate-sources">
+ <echo message="Running protoc ..."/>
+ <mkdir dir="${generated.sources.lite.dir}"/>
+ <exec executable="${protoc}">
+ <arg value="--java_out=lite:${generated.sources.lite.dir}"/>
+ <arg value="--proto_path=${protobuf.source.dir}"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/duration.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/empty.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/field_mask.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/source_context.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/struct.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/timestamp.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/type.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/wrappers.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/compiler/plugin.proto"/>
+ </exec>
+</project>
diff --git a/third_party/protobuf/java/lite/generate-test-sources-build.xml b/third_party/protobuf/java/lite/generate-test-sources-build.xml
new file mode 100644
index 0000000000..cdd1ee89a7
--- /dev/null
+++ b/third_party/protobuf/java/lite/generate-test-sources-build.xml
@@ -0,0 +1,43 @@
+<project name="generate-test-sources">
+ <mkdir dir="${generated.testsources.lite.dir}"/>
+ <exec executable="${protoc}">
+ <arg value="--java_out=lite:${generated.testsources.lite.dir}"/>
+ <arg value="--proto_path=${protobuf.source.dir}"/>
+ <arg value="--proto_path=${test.proto.dir}"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset_wire_format.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_custom_options.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public_lite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_lite_imports_nonlite.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_enormous_descriptor.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
+ <arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/lazy_fields_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/lite_equals_and_hash.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/multiple_files_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_builders_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_extension.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/nested_extension_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/non_nested_extension_lite.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test2.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/outer_class_name_test3.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/test_custom_options.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/field_presence_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_lite_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_for_proto2_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
+ <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
+ </exec>
+</project>
diff --git a/third_party/protobuf/java/lite/pom.xml b/third_party/protobuf/java/lite/pom.xml
new file mode 100644
index 0000000000..d7b150972d
--- /dev/null
+++ b/third_party/protobuf/java/lite/pom.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-parent</artifactId>
+ <version>3.0.0</version>
+ </parent>
+
+ <artifactId>protobuf-lite</artifactId>
+ <packaging>bundle</packaging>
+
+ <name>Protocol Buffers [Lite]</name>
+ <description>A trimmed-down version of the Protocol Buffers library.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <core.root>../core</core.root>
+ <test.proto.dir>${core.root}/src/test/proto</test.proto.dir>
+ </properties>
+
+ <build>
+ <sourceDirectory>${core.root}/src/main/java</sourceDirectory>
+ <testSourceDirectory>${core.root}/src/test/java</testSourceDirectory>
+
+ <plugins>
+ <!-- Use Antrun plugin to generate sources with protoc -->
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <!-- Generate core protos -->
+ <execution>
+ <id>generate-sources</id>
+ <phase>generate-sources</phase>
+ <configuration>
+ <target>
+ <ant antfile="generate-sources-build.xml"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <!-- Generate the test protos -->
+ <execution>
+ <id>generate-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <configuration>
+ <target>
+ <ant antfile="generate-test-sources-build.xml"/>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Only compile a subset of the files -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-generated-sources</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${generated.sources.lite.dir}</source>
+ </sources>
+ </configuration>
+ </execution>
+ <execution>
+ <id>add-generated-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${generated.testsources.lite.dir}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/AbstractMessageLite.java</include>
+ <include>**/AbstractParser.java</include>
+ <include>**/AbstractProtobufList.java</include>
+ <include>**/BooleanArrayList.java</include>
+ <include>**/ByteString.java</include>
+ <include>**/CodedInputStream.java</include>
+ <include>**/CodedOutputStream.java</include>
+ <include>**/DoubleArrayList.java</include>
+ <include>**/ExtensionLite.java</include>
+ <include>**/ExtensionRegistryLite.java</include>
+ <include>**/FieldSet.java</include>
+ <include>**/FloatArrayList.java</include>
+ <include>**/GeneratedMessageLite.java</include>
+ <include>**/IntArrayList.java</include>
+ <include>**/Internal.java</include>
+ <include>**/InvalidProtocolBufferException.java</include>
+ <include>**/LazyFieldLite.java</include>
+ <include>**/LazyStringArrayList.java</include>
+ <include>**/LazyStringList.java</include>
+ <include>**/LongArrayList.java</include>
+ <include>**/MapEntryLite.java</include>
+ <include>**/MapFieldLite.java</include>
+ <include>**/MessageLite.java</include>
+ <include>**/MessageLiteOrBuilder.java</include>
+ <include>**/MessageLiteToString.java</include>
+ <include>**/MutabilityOracle.java</include>
+ <include>**/NioByteString.java</include>
+ <include>**/Parser.java</include>
+ <include>**/ProtobufArrayList.java</include>
+ <include>**/ProtocolStringList.java</include>
+ <include>**/RopeByteString.java</include>
+ <include>**/SmallSortedMap.java</include>
+ <include>**/TextFormatEscaper.java</include>
+ <include>**/UninitializedMessageException.java</include>
+ <include>**/UnknownFieldSetLite.java</include>
+ <include>**/UnmodifiableLazyStringList.java</include>
+ <include>**/UnsafeByteOperations.java</include>
+ <include>**/Utf8.java</include>
+ <include>**/WireFormat.java</include>
+ </includes>
+ <testIncludes>
+ <testInclude>**/*Lite.java</testInclude>
+ <testInclude>**/BooleanArrayListTest.java</testInclude>
+ <testInclude>**/DoubleArrayListTest.java</testInclude>
+ <testInclude>**/FloatArrayListTest.java</testInclude>
+ <testInclude>**/IntArrayListTest.java</testInclude>
+ <testInclude>**/LazyMessageLiteTest.java</testInclude>
+ <testInclude>**/LiteTest.java</testInclude>
+ <testInclude>**/LongArrayListTest.java</testInclude>
+ <testInclude>**/NioByteStringTest.java</testInclude>
+ <testInclude>**/ProtobufArrayListTest.java</testInclude>
+ <testInclude>**/UnknownFieldSetLiteTest.java</testInclude>
+ </testIncludes>
+ </configuration>
+ </plugin>
+
+ <!-- OSGI bundle configuration -->
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+ <Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
+ <Export-Package>com.google.${project.artifactId};version=${project.version}</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/third_party/protobuf/java/pom.xml b/third_party/protobuf/java/pom.xml
new file mode 100644
index 0000000000..f89e442246
--- /dev/null
+++ b/third_party/protobuf/java/pom.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google</groupId>
+ <artifactId>google</artifactId>
+ <version>1</version>
+ </parent>
+
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-parent</artifactId>
+ <version>3.2.0</version>
+ <packaging>pom</packaging>
+
+ <name>Protocol Buffers [Parent]</name>
+ <inceptionYear>2008</inceptionYear>
+ <url>https://developers.google.com/protocol-buffers/</url>
+ <description>
+ Protocol Buffers are a way of encoding structured data in an efficient yet
+ extensible format.
+ </description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+ <!-- These are relative to the submodules -->
+ <protobuf.basedir>${project.basedir}/../..</protobuf.basedir>
+ <protobuf.source.dir>${protobuf.basedir}/src</protobuf.source.dir>
+ <protoc>${protobuf.source.dir}/protoc</protoc>
+ <test.proto.dir>src/test/proto</test.proto.dir>
+ <generated.sources.dir>${project.build.directory}/generated-sources</generated.sources.dir>
+ <generated.testsources.dir>${project.build.directory}/generated-test-sources</generated.testsources.dir>
+ <generated.sources.lite.dir>${project.build.directory}/generated-sources-lite</generated.sources.lite.dir>
+ <generated.testsources.lite.dir>${project.build.directory}/generated-test-sources-lite</generated.testsources.lite.dir>
+ </properties>
+
+ <licenses>
+ <license>
+ <name>3-Clause BSD License</name>
+ <url>https://opensource.org/licenses/BSD-3-Clause</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <scm>
+ <url>https://github.com/google/protobuf</url>
+ <connection>scm:git:https://github.com/google/protobuf.git</connection>
+ </scm>
+
+ <distributionManagement>
+ <snapshotRepository>
+ <id>sonatype-nexus-staging</id>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ </snapshotRepository>
+ <repository>
+ <id>sonatype-nexus-staging</id>
+ <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
+ </repository>
+ </distributionManagement>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>2.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>18.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.6.0</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.4</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.3</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.10</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>3.0.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.8</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-gpg-plugin</artifactId>
+ <version>1.6</version>
+ <executions>
+ <execution>
+ <id>sign-artifacts</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>sign</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <serverId>sonatype-nexus-staging</serverId>
+ <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+ <autoReleaseAfterClose>false</autoReleaseAfterClose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <modules>
+ <module>core</module>
+ <!-- <module>lite</module> -->
+ <module>util</module>
+ </modules>
+
+</project>
diff --git a/third_party/protobuf/java/util/pom.xml b/third_party/protobuf/java/util/pom.xml
new file mode 100644
index 0000000000..ac771f6ecc
--- /dev/null
+++ b/third_party/protobuf/java/util/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-parent</artifactId>
+ <version>3.2.0</version>
+ </parent>
+
+ <artifactId>protobuf-java-util</artifactId>
+ <packaging>bundle</packaging>
+
+ <name>Protocol Buffers [Util]</name>
+ <description>Utilities for Protocol Buffers</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <!-- Use the core proto dir so that we can call the core generation script -->
+ <test.proto.dir>../core/src/test/proto</test.proto.dir>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <!-- Generate the test protos -->
+ <execution>
+ <id>generate-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <configuration>
+ <target>
+ <!-- Generate all of the test protos from the core module -->
+ <ant antfile="../core/generate-test-sources-build.xml"/>
+
+ <!-- Generate additional test protos for this module -->
+ <exec executable="${protoc}">
+ <arg value="--java_out=${generated.testsources.dir}" />
+ <arg value="--proto_path=${protobuf.source.dir}" />
+ <arg value="--proto_path=src/test/proto" />
+ <arg value="src/test/proto/com/google/protobuf/util/json_test.proto" />
+ </exec>
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Add the generated test sources to the build -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>add-generated-test-sources</id>
+ <phase>generate-test-sources</phase>
+ <goals>
+ <goal>add-test-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${generated.testsources.dir}</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Configure the OSGI bundle -->
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
+ <Bundle-SymbolicName>com.google.protobuf.util</Bundle-SymbolicName>
+ <Export-Package>com.google.protobuf.util;version=${project.version}</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+
+ <!-- Configure the fat jar to include all dependencies -->
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Durations.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Durations.java
new file mode 100644
index 0000000000..46b2182865
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -0,0 +1,302 @@
+// 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.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.math.IntMath.checkedAdd;
+import static com.google.common.math.IntMath.checkedSubtract;
+import static com.google.common.math.LongMath.checkedAdd;
+import static com.google.common.math.LongMath.checkedMultiply;
+import static com.google.common.math.LongMath.checkedSubtract;
+import static com.google.protobuf.util.Timestamps.MICROS_PER_SECOND;
+import static com.google.protobuf.util.Timestamps.MILLIS_PER_SECOND;
+import static com.google.protobuf.util.Timestamps.NANOS_PER_MICROSECOND;
+import static com.google.protobuf.util.Timestamps.NANOS_PER_MILLISECOND;
+import static com.google.protobuf.util.Timestamps.NANOS_PER_SECOND;
+
+import com.google.protobuf.Duration;
+import java.text.ParseException;
+import java.util.Comparator;
+
+/**
+ * Utilities to help create/manipulate {@code protobuf/duration.proto}. All operations throw an
+ * {@link IllegalArgumentException} if the input(s) are not {@linkplain #isValid(Duration) valid}.
+ */
+public final class Durations {
+ static final long DURATION_SECONDS_MIN = -315576000000L;
+ static final long DURATION_SECONDS_MAX = 315576000000L;
+
+ /** A constant holding the minimum valid {@link Duration}, approximately {@code -10,000} years. */
+ public static final Duration MIN_VALUE =
+ Duration.newBuilder().setSeconds(DURATION_SECONDS_MIN).setNanos(-999999999).build();
+
+ /** A constant holding the maximum valid {@link Duration}, approximately {@code +10,000} years. */
+ public static final Duration MAX_VALUE =
+ Duration.newBuilder().setSeconds(DURATION_SECONDS_MAX).setNanos(999999999).build();
+
+ private Durations() {}
+
+ private static final Comparator<Duration> COMPARATOR =
+ new Comparator<Duration>() {
+ @Override
+ public int compare(Duration d1, Duration d2) {
+ checkValid(d1);
+ checkValid(d2);
+ int secDiff = Long.compare(d1.getSeconds(), d2.getSeconds());
+ return (secDiff != 0) ? secDiff : Integer.compare(d1.getNanos(), d2.getNanos());
+ }
+ };
+
+ /**
+ * Returns a {@link Comparator} for {@link Duration}s which sorts in increasing chronological
+ * order. Nulls and invalid {@link Duration}s are not allowed (see {@link #isValid}).
+ */
+ public static Comparator<Duration> comparator() {
+ return COMPARATOR;
+ }
+
+ /**
+ * Returns true if the given {@link Duration} is valid. The {@code seconds} value must be in the
+ * range [-315,576,000,000, +315,576,000,000]. The {@code nanos} value must be in the range
+ * [-999,999,999, +999,999,999].
+ *
+ * <p><b>Note:</b> Durations less than one second are represented with a 0 {@code seconds} field
+ * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero
+ * value for the {@code nanos} field must be of the same sign as the {@code seconds} field.
+ */
+ public static boolean isValid(Duration duration) {
+ return isValid(duration.getSeconds(), duration.getNanos());
+ }
+
+ /**
+ * Returns true if the given number of seconds and nanos is a valid {@link Duration}. The {@code
+ * seconds} value must be in the range [-315,576,000,000, +315,576,000,000]. The {@code nanos}
+ * value must be in the range [-999,999,999, +999,999,999].
+ *
+ * <p><b>Note:</b> Durations less than one second are represented with a 0 {@code seconds} field
+ * and a positive or negative {@code nanos} field. For durations of one second or more, a non-zero
+ * value for the {@code nanos} field must be of the same sign as the {@code seconds} field.
+ */
+ public static boolean isValid(long seconds, int nanos) {
+ if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
+ return false;
+ }
+ if (nanos < -999999999L || nanos >= NANOS_PER_SECOND) {
+ return false;
+ }
+ if (seconds < 0 || nanos < 0) {
+ if (seconds > 0 || nanos > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Throws an {@link IllegalArgumentException} if the given {@link Duration} is not valid. */
+ public static Duration checkValid(Duration duration) {
+ long seconds = duration.getSeconds();
+ int nanos = duration.getNanos();
+ checkArgument(
+ isValid(seconds, nanos),
+ "Duration is not valid. See proto definition for valid values. "
+ + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
+ + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
+ + "Nanos must have the same sign as seconds",
+ seconds,
+ nanos);
+ return duration;
+ }
+
+ /**
+ * Convert Duration to string format. The string format will contains 3, 6, or 9 fractional digits
+ * depending on the precision required to represent the exact Duration value. For example: "1s",
+ * "1.010s", "1.000000100s", "-3.100s" The range that can be represented by Duration is from
+ * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
+ *
+ * @return The string representation of the given duration.
+ * @throws IllegalArgumentException if the given duration is not in the valid range.
+ */
+ public static String toString(Duration duration) {
+ checkValid(duration);
+
+ long seconds = duration.getSeconds();
+ int nanos = duration.getNanos();
+
+ StringBuilder result = new StringBuilder();
+ if (seconds < 0 || nanos < 0) {
+ result.append("-");
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ result.append(seconds);
+ if (nanos != 0) {
+ result.append(".");
+ result.append(Timestamps.formatNanos(nanos));
+ }
+ result.append("s");
+ return result.toString();
+ }
+
+ /**
+ * Parse from a string to produce a duration.
+ *
+ * @return A Duration parsed from the string.
+ * @throws ParseException if parsing fails.
+ */
+ public static Duration parse(String value) throws ParseException {
+ // Must ended with "s".
+ if (value.isEmpty() || value.charAt(value.length() - 1) != 's') {
+ throw new ParseException("Invalid duration string: " + value, 0);
+ }
+ boolean negative = false;
+ if (value.charAt(0) == '-') {
+ negative = true;
+ value = value.substring(1);
+ }
+ String secondValue = value.substring(0, value.length() - 1);
+ String nanoValue = "";
+ int pointPosition = secondValue.indexOf('.');
+ if (pointPosition != -1) {
+ nanoValue = secondValue.substring(pointPosition + 1);
+ secondValue = secondValue.substring(0, pointPosition);
+ }
+ long seconds = Long.parseLong(secondValue);
+ int nanos = nanoValue.isEmpty() ? 0 : Timestamps.parseNanos(nanoValue);
+ if (seconds < 0) {
+ throw new ParseException("Invalid duration string: " + value, 0);
+ }
+ if (negative) {
+ seconds = -seconds;
+ nanos = -nanos;
+ }
+ try {
+ return normalizedDuration(seconds, nanos);
+ } catch (IllegalArgumentException e) {
+ throw new ParseException("Duration value is out of range.", 0);
+ }
+ }
+
+ /** Create a Duration from the number of seconds. */
+ public static Duration fromSeconds(long seconds) {
+ return normalizedDuration(seconds, 0);
+ }
+
+ /**
+ * Convert a Duration to the number of seconds. The result will be rounded towards 0 to the
+ * nearest second. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
+ */
+ public static long toSeconds(Duration duration) {
+ return checkValid(duration).getSeconds();
+ }
+
+ /** Create a Duration from the number of milliseconds. */
+ public static Duration fromMillis(long milliseconds) {
+ return normalizedDuration(
+ milliseconds / MILLIS_PER_SECOND,
+ (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+ }
+
+ /**
+ * Convert a Duration to the number of milliseconds. The result will be rounded towards 0 to the
+ * nearest millisecond. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
+ */
+ public static long toMillis(Duration duration) {
+ checkValid(duration);
+ return checkedAdd(
+ checkedMultiply(duration.getSeconds(), MILLIS_PER_SECOND),
+ duration.getNanos() / NANOS_PER_MILLISECOND);
+ }
+
+ /** Create a Duration from the number of microseconds. */
+ public static Duration fromMicros(long microseconds) {
+ return normalizedDuration(
+ microseconds / MICROS_PER_SECOND,
+ (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+ }
+
+ /**
+ * Convert a Duration to the number of microseconds. The result will be rounded towards 0 to the
+ * nearest microseconds. E.g., if the duration represents -1 nanosecond, it will be rounded to 0.
+ */
+ public static long toMicros(Duration duration) {
+ checkValid(duration);
+ return checkedAdd(
+ checkedMultiply(duration.getSeconds(), MICROS_PER_SECOND),
+ duration.getNanos() / NANOS_PER_MICROSECOND);
+ }
+
+ /** Create a Duration from the number of nanoseconds. */
+ public static Duration fromNanos(long nanoseconds) {
+ return normalizedDuration(
+ nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
+ }
+
+ /** Convert a Duration to the number of nanoseconds. */
+ public static long toNanos(Duration duration) {
+ checkValid(duration);
+ return checkedAdd(
+ checkedMultiply(duration.getSeconds(), NANOS_PER_SECOND), duration.getNanos());
+ }
+
+ /** Add two durations. */
+ public static Duration add(Duration d1, Duration d2) {
+ checkValid(d1);
+ checkValid(d2);
+ return normalizedDuration(
+ checkedAdd(d1.getSeconds(), d2.getSeconds()), checkedAdd(d1.getNanos(), d2.getNanos()));
+ }
+
+ /** Subtract a duration from another. */
+ public static Duration subtract(Duration d1, Duration d2) {
+ checkValid(d1);
+ checkValid(d2);
+ return normalizedDuration(
+ checkedSubtract(d1.getSeconds(), d2.getSeconds()),
+ checkedSubtract(d1.getNanos(), d2.getNanos()));
+ }
+
+ static Duration normalizedDuration(long seconds, int nanos) {
+ if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+ seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
+ nanos %= NANOS_PER_SECOND;
+ }
+ if (seconds > 0 && nanos < 0) {
+ nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
+ seconds--; // no overflow since seconds is positive (and we're decrementing)
+ }
+ if (seconds < 0 && nanos > 0) {
+ nanos -= NANOS_PER_SECOND; // no overflow since nanos is positive (and we're subtracting)
+ seconds++; // no overflow since seconds is negative (and we're incrementing)
+ }
+ Duration duration = Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+ return checkValid(duration);
+ }
+}
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
new file mode 100644
index 0000000000..b192b53edf
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskTree.java
@@ -0,0 +1,287 @@
+// 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.util;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Message;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.logging.Logger;
+
+/**
+ * A tree representation of a FieldMask. Each leaf node in this tree represent
+ * a field path in the FieldMask.
+ *
+ * <p>For example, FieldMask "foo.bar,foo.baz,bar.baz" as a tree will be:
+ * <pre>
+ * [root] -+- foo -+- bar
+ * | |
+ * | +- baz
+ * |
+ * +- bar --- baz
+ * </pre>
+ *
+ * <p>By representing FieldMasks with this tree structure we can easily convert
+ * a FieldMask to a canonical form, merge two FieldMasks, calculate the
+ * intersection to two FieldMasks and traverse all fields specified by the
+ * FieldMask in a message tree.
+ */
+final class FieldMaskTree {
+ private static final Logger logger = Logger.getLogger(FieldMaskTree.class.getName());
+
+ private static final String FIELD_PATH_SEPARATOR_REGEX = "\\.";
+
+ private static final class Node {
+ final SortedMap<String, Node> children = new TreeMap<String, Node>();
+ }
+
+ private final Node root = new Node();
+
+ /**
+ * Creates an empty FieldMaskTree.
+ */
+ FieldMaskTree() {}
+
+ /**
+ * Creates a FieldMaskTree for a given FieldMask.
+ */
+ FieldMaskTree(FieldMask mask) {
+ mergeFromFieldMask(mask);
+ }
+
+ @Override
+ public String toString() {
+ return FieldMaskUtil.toString(toFieldMask());
+ }
+
+ /**
+ * Adds a field path to the tree. In a FieldMask, every field path matches the
+ * specified field as well as all its sub-fields. For example, a field path
+ * "foo.bar" matches field "foo.bar" and also "foo.bar.baz", etc. When adding
+ * a field path to the tree, redundant sub-paths will be removed. That is,
+ * after adding "foo.bar" to the tree, "foo.bar.baz" will be removed if it
+ * exists, which will turn the tree node for "foo.bar" to a leaf node.
+ * Likewise, if the field path to add is a sub-path of an existing leaf node,
+ * nothing will be changed in the tree.
+ */
+ FieldMaskTree addFieldPath(String path) {
+ String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return this;
+ }
+ Node node = root;
+ boolean createNewBranch = false;
+ // Find the matching node in the tree.
+ for (String part : parts) {
+ // Check whether the path matches an existing leaf node.
+ if (!createNewBranch && node != root && node.children.isEmpty()) {
+ // The path to add is a sub-path of an existing leaf node.
+ return this;
+ }
+ if (node.children.containsKey(part)) {
+ node = node.children.get(part);
+ } else {
+ createNewBranch = true;
+ Node tmp = new Node();
+ node.children.put(part, tmp);
+ node = tmp;
+ }
+ }
+ // Turn the matching node into a leaf node (i.e., remove sub-paths).
+ node.children.clear();
+ return this;
+ }
+
+ /**
+ * Merges all field paths in a FieldMask into this tree.
+ */
+ FieldMaskTree mergeFromFieldMask(FieldMask mask) {
+ for (String path : mask.getPathsList()) {
+ addFieldPath(path);
+ }
+ return this;
+ }
+
+ /**
+ * Converts this tree to a FieldMask.
+ */
+ FieldMask toFieldMask() {
+ if (root.children.isEmpty()) {
+ return FieldMask.getDefaultInstance();
+ }
+ List<String> paths = new ArrayList<String>();
+ getFieldPaths(root, "", paths);
+ return FieldMask.newBuilder().addAllPaths(paths).build();
+ }
+
+ /**
+ * Gathers all field paths in a sub-tree.
+ */
+ private void getFieldPaths(Node node, String path, List<String> paths) {
+ if (node.children.isEmpty()) {
+ paths.add(path);
+ return;
+ }
+ for (Entry<String, Node> entry : node.children.entrySet()) {
+ String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
+ getFieldPaths(entry.getValue(), childPath, paths);
+ }
+ }
+
+ /**
+ * Adds the intersection of this tree with the given {@code path} to {@code output}.
+ */
+ void intersectFieldPath(String path, FieldMaskTree output) {
+ if (root.children.isEmpty()) {
+ return;
+ }
+ String[] parts = path.split(FIELD_PATH_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return;
+ }
+ Node node = root;
+ for (String part : parts) {
+ if (node != root && node.children.isEmpty()) {
+ // The given path is a sub-path of an existing leaf node in the tree.
+ output.addFieldPath(path);
+ return;
+ }
+ if (node.children.containsKey(part)) {
+ node = node.children.get(part);
+ } else {
+ return;
+ }
+ }
+ // We found a matching node for the path. All leaf children of this matching
+ // node is in the intersection.
+ List<String> paths = new ArrayList<String>();
+ getFieldPaths(node, path, paths);
+ for (String value : paths) {
+ output.addFieldPath(value);
+ }
+ }
+
+ /**
+ * Merges all fields specified by this FieldMaskTree from {@code source} to {@code destination}.
+ */
+ void merge(Message source, Message.Builder destination, FieldMaskUtil.MergeOptions options) {
+ if (source.getDescriptorForType() != destination.getDescriptorForType()) {
+ throw new IllegalArgumentException("Cannot merge messages of different types.");
+ }
+ if (root.children.isEmpty()) {
+ return;
+ }
+ merge(root, "", source, destination, options);
+ }
+
+ /**
+ * Merges all fields specified by a sub-tree from {@code source} to {@code destination}.
+ */
+ private void merge(
+ Node node,
+ String path,
+ Message source,
+ Message.Builder destination,
+ FieldMaskUtil.MergeOptions options) {
+ if (source.getDescriptorForType() != destination.getDescriptorForType()) {
+ throw new IllegalArgumentException(
+ String.format(
+ "source (%s) and destination (%s) descriptor must be equal",
+ source.getDescriptorForType(), destination.getDescriptorForType()));
+ }
+
+ Descriptor descriptor = source.getDescriptorForType();
+ for (Entry<String, Node> entry : node.children.entrySet()) {
+ FieldDescriptor field = descriptor.findFieldByName(entry.getKey());
+ if (field == null) {
+ logger.warning(
+ "Cannot find field \""
+ + entry.getKey()
+ + "\" in message type "
+ + descriptor.getFullName());
+ continue;
+ }
+ if (!entry.getValue().children.isEmpty()) {
+ if (field.isRepeated() || field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
+ logger.warning(
+ "Field \""
+ + field.getFullName()
+ + "\" is not a "
+ + "singluar message field and cannot have sub-fields.");
+ continue;
+ }
+ String childPath = path.isEmpty() ? entry.getKey() : path + "." + entry.getKey();
+ merge(
+ entry.getValue(),
+ childPath,
+ (Message) source.getField(field),
+ destination.getFieldBuilder(field),
+ options);
+ continue;
+ }
+ if (field.isRepeated()) {
+ if (options.replaceRepeatedFields()) {
+ destination.setField(field, source.getField(field));
+ } else {
+ for (Object element : (List) source.getField(field)) {
+ destination.addRepeatedField(field, element);
+ }
+ }
+ } else {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ if (options.replaceMessageFields()) {
+ if (!source.hasField(field)) {
+ destination.clearField(field);
+ } else {
+ destination.setField(field, source.getField(field));
+ }
+ } else {
+ if (source.hasField(field)) {
+ destination.getFieldBuilder(field).mergeFrom((Message) source.getField(field));
+ }
+ }
+ } else {
+ if (source.hasField(field) || !options.replacePrimitiveFields()) {
+ destination.setField(field, source.getField(field));
+ } else {
+ destination.clearField(field);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
new file mode 100644
index 0000000000..21d11b2ce7
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -0,0 +1,342 @@
+// 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.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import com.google.common.primitives.Ints;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.Internal;
+import com.google.protobuf.Message;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Utility helper functions to work with {@link com.google.protobuf.FieldMask}.
+ */
+public class FieldMaskUtil {
+ private static final String FIELD_PATH_SEPARATOR = ",";
+ private static final String FIELD_PATH_SEPARATOR_REGEX = ",";
+ private static final String FIELD_SEPARATOR_REGEX = "\\.";
+
+ private FieldMaskUtil() {}
+
+ /**
+ * Converts a FieldMask to a string.
+ */
+ public static String toString(FieldMask fieldMask) {
+ // TODO(xiaofeng): Consider using com.google.common.base.Joiner here instead.
+ StringBuilder result = new StringBuilder();
+ boolean first = true;
+ for (String value : fieldMask.getPathsList()) {
+ if (value.isEmpty()) {
+ // Ignore empty paths.
+ continue;
+ }
+ if (first) {
+ first = false;
+ } else {
+ result.append(FIELD_PATH_SEPARATOR);
+ }
+ result.append(value);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Parses from a string to a FieldMask.
+ */
+ public static FieldMask fromString(String value) {
+ // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
+ return fromStringList(null, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+ }
+
+ /**
+ * Parses from a string to a FieldMask and validates all field paths.
+ *
+ * @throws IllegalArgumentException if any of the field path is invalid.
+ */
+ public static FieldMask fromString(Class<? extends Message> type, String value) {
+ // TODO(xiaofeng): Consider using com.google.common.base.Splitter here instead.
+ return fromStringList(type, Arrays.asList(value.split(FIELD_PATH_SEPARATOR_REGEX)));
+ }
+
+ /**
+ * Constructs a FieldMask for a list of field paths in a certain type.
+ *
+ * @throws IllegalArgumentException if any of the field path is not valid.
+ */
+ // TODO(xiaofeng): Consider renaming fromStrings()
+ public static FieldMask fromStringList(Class<? extends Message> type, Iterable<String> paths) {
+ FieldMask.Builder builder = FieldMask.newBuilder();
+ for (String path : paths) {
+ if (path.isEmpty()) {
+ // Ignore empty field paths.
+ continue;
+ }
+ if (type != null && !isValid(type, path)) {
+ throw new IllegalArgumentException(path + " is not a valid path for " + type);
+ }
+ builder.addPaths(path);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Constructs a FieldMask from the passed field numbers.
+ *
+ * @throws IllegalArgumentException if any of the fields are invalid for the message.
+ */
+ public static FieldMask fromFieldNumbers(Class<? extends Message> type, int... fieldNumbers) {
+ return fromFieldNumbers(type, Ints.asList(fieldNumbers));
+ }
+
+ /**
+ * Constructs a FieldMask from the passed field numbers.
+ *
+ * @throws IllegalArgumentException if any of the fields are invalid for the message.
+ */
+ public static FieldMask fromFieldNumbers(
+ Class<? extends Message> type, Iterable<Integer> fieldNumbers) {
+ Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
+
+ FieldMask.Builder builder = FieldMask.newBuilder();
+ for (Integer fieldNumber : fieldNumbers) {
+ FieldDescriptor field = descriptor.findFieldByNumber(fieldNumber);
+ checkArgument(
+ field != null,
+ String.format("%s is not a valid field number for %s.", fieldNumber, type));
+ builder.addPaths(field.getName());
+ }
+ return builder.build();
+ }
+
+ /**
+ * Converts a field mask to a Proto3 JSON string, that is converting from snake case to camel
+ * case and joining all paths into one string with commas.
+ */
+ public static String toJsonString(FieldMask fieldMask) {
+ List<String> paths = new ArrayList<String>(fieldMask.getPathsCount());
+ for (String path : fieldMask.getPathsList()) {
+ if (path.isEmpty()) {
+ continue;
+ }
+ paths.add(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, path));
+ }
+ return Joiner.on(FIELD_PATH_SEPARATOR).join(paths);
+ }
+
+ /**
+ * Converts a field mask from a Proto3 JSON string, that is splitting the paths along commas and
+ * converting from camel case to snake case.
+ */
+ public static FieldMask fromJsonString(String value) {
+ Iterable<String> paths = Splitter.on(FIELD_PATH_SEPARATOR).split(value);
+ FieldMask.Builder builder = FieldMask.newBuilder();
+ for (String path : paths) {
+ if (path.isEmpty()) {
+ continue;
+ }
+ builder.addPaths(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, path));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Checks whether paths in a given fields mask are valid.
+ */
+ public static boolean isValid(Class<? extends Message> type, FieldMask fieldMask) {
+ Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
+
+ return isValid(descriptor, fieldMask);
+ }
+
+ /**
+ * Checks whether paths in a given fields mask are valid.
+ */
+ public static boolean isValid(Descriptor descriptor, FieldMask fieldMask) {
+ for (String path : fieldMask.getPathsList()) {
+ if (!isValid(descriptor, path)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether a given field path is valid.
+ */
+ public static boolean isValid(Class<? extends Message> type, String path) {
+ Descriptor descriptor = Internal.getDefaultInstance(type).getDescriptorForType();
+
+ return isValid(descriptor, path);
+ }
+
+ /**
+ * Checks whether paths in a given fields mask are valid.
+ */
+ public static boolean isValid(Descriptor descriptor, String path) {
+ String[] parts = path.split(FIELD_SEPARATOR_REGEX);
+ if (parts.length == 0) {
+ return false;
+ }
+ for (String name : parts) {
+ if (descriptor == null) {
+ return false;
+ }
+ FieldDescriptor field = descriptor.findFieldByName(name);
+ if (field == null) {
+ return false;
+ }
+ if (!field.isRepeated() && field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ descriptor = field.getMessageType();
+ } else {
+ descriptor = null;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Converts a FieldMask to its canonical form. In the canonical form of a
+ * FieldMask, all field paths are sorted alphabetically and redundant field
+ * paths are moved.
+ */
+ public static FieldMask normalize(FieldMask mask) {
+ return new FieldMaskTree(mask).toFieldMask();
+ }
+
+ /**
+ * Creates a union of two or more FieldMasks.
+ */
+ public static FieldMask union(
+ FieldMask firstMask, FieldMask secondMask, FieldMask... otherMasks) {
+ FieldMaskTree maskTree = new FieldMaskTree(firstMask).mergeFromFieldMask(secondMask);
+ for (FieldMask mask : otherMasks) {
+ maskTree.mergeFromFieldMask(mask);
+ }
+ return maskTree.toFieldMask();
+ }
+
+ /**
+ * Calculates the intersection of two FieldMasks.
+ */
+ public static FieldMask intersection(FieldMask mask1, FieldMask mask2) {
+ FieldMaskTree tree = new FieldMaskTree(mask1);
+ FieldMaskTree result = new FieldMaskTree();
+ for (String path : mask2.getPathsList()) {
+ tree.intersectFieldPath(path, result);
+ }
+ return result.toFieldMask();
+ }
+
+ /**
+ * Options to customize merging behavior.
+ */
+ public static final class MergeOptions {
+ private boolean replaceMessageFields = false;
+ private boolean replaceRepeatedFields = false;
+ // TODO(b/28277137): change the default behavior to always replace primitive fields after
+ // fixing all failing TAP tests.
+ private boolean replacePrimitiveFields = false;
+
+ /**
+ * Whether to replace message fields (i.e., discard existing content in
+ * destination message fields) when merging.
+ * Default behavior is to merge the source message field into the
+ * destination message field.
+ */
+ public boolean replaceMessageFields() {
+ return replaceMessageFields;
+ }
+
+ /**
+ * Whether to replace repeated fields (i.e., discard existing content in
+ * destination repeated fields) when merging.
+ * Default behavior is to append elements from source repeated field to the
+ * destination repeated field.
+ */
+ public boolean replaceRepeatedFields() {
+ return replaceRepeatedFields;
+ }
+
+ /**
+ * Whether to replace primitive (non-repeated and non-message) fields in
+ * destination message fields with the source primitive fields (i.e., if the
+ * field is set in the source, the value is copied to the
+ * destination; if the field is unset in the source, the field is cleared
+ * from the destination) when merging.
+ *
+ * <p>Default behavior is to always set the value of the source primitive
+ * field to the destination primitive field, and if the source field is
+ * unset, the default value of the source field is copied to the
+ * destination.
+ */
+ public boolean replacePrimitiveFields() {
+ return replacePrimitiveFields;
+ }
+
+ public void setReplaceMessageFields(boolean value) {
+ replaceMessageFields = value;
+ }
+
+ public void setReplaceRepeatedFields(boolean value) {
+ replaceRepeatedFields = value;
+ }
+
+ public void setReplacePrimitiveFields(boolean value) {
+ replacePrimitiveFields = value;
+ }
+ }
+
+ /**
+ * Merges fields specified by a FieldMask from one message to another with the
+ * specified merge options.
+ */
+ public static void merge(
+ FieldMask mask, Message source, Message.Builder destination, MergeOptions options) {
+ new FieldMaskTree(mask).merge(source, destination, options);
+ }
+
+ /**
+ * Merges fields specified by a FieldMask from one message to another.
+ */
+ public static void merge(FieldMask mask, Message source, Message.Builder destination) {
+ merge(mask, source, destination, new MergeOptions());
+ }
+}
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
new file mode 100644
index 0000000000..838700f7f6
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -0,0 +1,1766 @@
+// 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.util;
+
+import com.google.common.io.BaseEncoding;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.stream.JsonReader;
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.EnumDescriptor;
+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.DoubleValue;
+import com.google.protobuf.Duration;
+import com.google.protobuf.DynamicMessage;
+import com.google.protobuf.FieldMask;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.protobuf.NullValue;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.Timestamp;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.logging.Logger;
+
+/**
+ * Utility classes to convert protobuf messages to/from JSON format. The JSON
+ * format follows Proto3 JSON specification and only proto3 features are
+ * supported. Proto2 only features (e.g., extensions and unknown fields) will
+ * be discarded in the conversion. That is, when converting proto2 messages
+ * to JSON format, extensions and unknown fields will be treated as if they
+ * do not exist. This applies to proto2 messages embedded in proto3 messages
+ * as well.
+ */
+public class JsonFormat {
+ private static final Logger logger = Logger.getLogger(JsonFormat.class.getName());
+
+ private JsonFormat() {}
+
+ /**
+ * Creates a {@link Printer} with default configurations.
+ */
+ public static Printer printer() {
+ return new Printer(TypeRegistry.getEmptyTypeRegistry(), false, false, false);
+ }
+
+ /**
+ * A Printer converts protobuf message to JSON format.
+ */
+ public static class Printer {
+ private final TypeRegistry registry;
+ private final boolean includingDefaultValueFields;
+ private final boolean preservingProtoFieldNames;
+ private final boolean omittingInsignificantWhitespace;
+
+ private Printer(
+ TypeRegistry registry,
+ boolean includingDefaultValueFields,
+ boolean preservingProtoFieldNames,
+ boolean omittingInsignificantWhitespace) {
+ this.registry = registry;
+ this.includingDefaultValueFields = includingDefaultValueFields;
+ this.preservingProtoFieldNames = preservingProtoFieldNames;
+ this.omittingInsignificantWhitespace = omittingInsignificantWhitespace;
+ }
+
+ /**
+ * Creates a new {@link Printer} using the given registry. The new Printer
+ * clones all other configurations from the current {@link Printer}.
+ *
+ * @throws IllegalArgumentException if a registry is already set.
+ */
+ public Printer usingTypeRegistry(TypeRegistry registry) {
+ if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+ throw new IllegalArgumentException("Only one registry is allowed.");
+ }
+ return new Printer(
+ registry,
+ includingDefaultValueFields,
+ preservingProtoFieldNames,
+ omittingInsignificantWhitespace);
+ }
+
+ /**
+ * Creates a new {@link Printer} that will also print fields set to their
+ * defaults. Empty repeated fields and map fields will be printed as well.
+ * The new Printer clones all other configurations from the current
+ * {@link Printer}.
+ */
+ public Printer includingDefaultValueFields() {
+ return new Printer(
+ registry, true, preservingProtoFieldNames, omittingInsignificantWhitespace);
+ }
+
+ /**
+ * Creates a new {@link Printer} that is configured to use the original proto
+ * field names as defined in the .proto file rather than converting them to
+ * lowerCamelCase. The new Printer clones all other configurations from the
+ * current {@link Printer}.
+ */
+ public Printer preservingProtoFieldNames() {
+ return new Printer(
+ registry, includingDefaultValueFields, true, omittingInsignificantWhitespace);
+ }
+
+
+ /**
+ * Create a new {@link Printer} that will omit all insignificant whitespace
+ * in the JSON output. This new Printer clones all other configurations from the
+ * current Printer. Insignificant whitespace is defined by the JSON spec as whitespace
+ * that appear between JSON structural elements:
+ * <pre>
+ * ws = *(
+ * %x20 / ; Space
+ * %x09 / ; Horizontal tab
+ * %x0A / ; Line feed or New line
+ * %x0D ) ; Carriage return
+ * </pre>
+ * See <a href="https://tools.ietf.org/html/rfc7159">https://tools.ietf.org/html/rfc7159</a>
+ * current {@link Printer}.
+ */
+ public Printer omittingInsignificantWhitespace() {
+ return new Printer(registry, includingDefaultValueFields, preservingProtoFieldNames, true);
+ }
+
+ /**
+ * Converts a protobuf message to JSON format.
+ *
+ * @throws InvalidProtocolBufferException if the message contains Any types
+ * that can't be resolved.
+ * @throws IOException if writing to the output fails.
+ */
+ public void appendTo(MessageOrBuilder message, Appendable output) throws IOException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new PrinterImpl(
+ registry,
+ includingDefaultValueFields,
+ preservingProtoFieldNames,
+ output,
+ omittingInsignificantWhitespace)
+ .print(message);
+ }
+
+ /**
+ * Converts a protobuf message to JSON format. Throws exceptions if there
+ * are unknown Any types in the message.
+ */
+ public String print(MessageOrBuilder message) throws InvalidProtocolBufferException {
+ try {
+ StringBuilder builder = new StringBuilder();
+ appendTo(message, builder);
+ return builder.toString();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IOException e) {
+ // Unexpected IOException.
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ /**
+ * Creates a {@link Parser} with default configuration.
+ */
+ public static Parser parser() {
+ return new Parser(TypeRegistry.getEmptyTypeRegistry(), false, Parser.DEFAULT_RECURSION_LIMIT);
+ }
+
+ /**
+ * A Parser parses JSON to protobuf message.
+ */
+ public static class Parser {
+ private final TypeRegistry registry;
+ private final boolean ignoringUnknownFields;
+ private final int recursionLimit;
+
+ // The default parsing recursion limit is aligned with the proto binary parser.
+ private static final int DEFAULT_RECURSION_LIMIT = 100;
+
+ private Parser(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
+ this.registry = registry;
+ this.ignoringUnknownFields = ignoreUnknownFields;
+ this.recursionLimit = recursionLimit;
+ }
+
+ /**
+ * Creates a new {@link Parser} using the given registry. The new Parser
+ * clones all other configurations from this Parser.
+ *
+ * @throws IllegalArgumentException if a registry is already set.
+ */
+ public Parser usingTypeRegistry(TypeRegistry registry) {
+ if (this.registry != TypeRegistry.getEmptyTypeRegistry()) {
+ throw new IllegalArgumentException("Only one registry is allowed.");
+ }
+ return new Parser(registry, ignoringUnknownFields, recursionLimit);
+ }
+
+ /**
+ * Creates a new {@link Parser} configured to not throw an exception when an unknown field is
+ * encountered. The new Parser clones all other configurations from this Parser.
+ */
+ public Parser ignoringUnknownFields() {
+ return new Parser(this.registry, true, recursionLimit);
+ }
+
+ /**
+ * Parses from JSON into a protobuf message.
+ *
+ * @throws InvalidProtocolBufferException if the input is not valid JSON
+ * format or there are unknown fields in the input.
+ */
+ public void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
+ }
+
+ /**
+ * Parses from JSON into a protobuf message.
+ *
+ * @throws InvalidProtocolBufferException if the input is not valid JSON
+ * format or there are unknown fields in the input.
+ * @throws IOException if reading from the input throws.
+ */
+ public void merge(Reader json, Message.Builder builder) throws IOException {
+ // TODO(xiaofeng): Investigate the allocation overhead and optimize for
+ // mobile.
+ new ParserImpl(registry, ignoringUnknownFields, recursionLimit).merge(json, builder);
+ }
+
+ // For testing only.
+ Parser usingRecursionLimit(int recursionLimit) {
+ return new Parser(registry, ignoringUnknownFields, recursionLimit);
+ }
+ }
+
+ /**
+ * A TypeRegistry is used to resolve Any messages in the JSON conversion.
+ * You must provide a TypeRegistry containing all message types used in
+ * Any message fields, or the JSON conversion will fail because data
+ * in Any message fields is unrecognizable. You don't need to supply a
+ * TypeRegistry if you don't use Any message fields.
+ */
+ public static class TypeRegistry {
+ private static class EmptyTypeRegistryHolder {
+ private static final TypeRegistry EMPTY =
+ new TypeRegistry(Collections.<String, Descriptor>emptyMap());
+ }
+
+ public static TypeRegistry getEmptyTypeRegistry() {
+ return EmptyTypeRegistryHolder.EMPTY;
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Find a type by its full name. Returns null if it cannot be found in
+ * this {@link TypeRegistry}.
+ */
+ public Descriptor find(String name) {
+ return types.get(name);
+ }
+
+ private final Map<String, Descriptor> types;
+
+ private TypeRegistry(Map<String, Descriptor> types) {
+ this.types = types;
+ }
+
+ /**
+ * A Builder is used to build {@link TypeRegistry}.
+ */
+ public static class Builder {
+ private Builder() {}
+
+ /**
+ * Adds a message type and all types defined in the same .proto file as
+ * well as all transitively imported .proto files to this {@link Builder}.
+ */
+ public Builder add(Descriptor messageType) {
+ if (types == null) {
+ throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
+ }
+ addFile(messageType.getFile());
+ return this;
+ }
+
+ /**
+ * Adds message types and all types defined in the same .proto file as
+ * well as all transitively imported .proto files to this {@link Builder}.
+ */
+ public Builder add(Iterable<Descriptor> messageTypes) {
+ if (types == null) {
+ throw new IllegalStateException("A TypeRegistry.Builer can only be used once.");
+ }
+ for (Descriptor type : messageTypes) {
+ addFile(type.getFile());
+ }
+ return this;
+ }
+
+ /**
+ * Builds a {@link TypeRegistry}. This method can only be called once for
+ * one Builder.
+ */
+ public TypeRegistry build() {
+ TypeRegistry result = new TypeRegistry(types);
+ // Make sure the built {@link TypeRegistry} is immutable.
+ types = null;
+ return result;
+ }
+
+ private void addFile(FileDescriptor file) {
+ // Skip the file if it's already added.
+ if (!files.add(file.getFullName())) {
+ return;
+ }
+ for (FileDescriptor dependency : file.getDependencies()) {
+ addFile(dependency);
+ }
+ for (Descriptor message : file.getMessageTypes()) {
+ addMessage(message);
+ }
+ }
+
+ private void addMessage(Descriptor message) {
+ for (Descriptor nestedType : message.getNestedTypes()) {
+ addMessage(nestedType);
+ }
+
+ if (types.containsKey(message.getFullName())) {
+ logger.warning("Type " + message.getFullName() + " is added multiple times.");
+ return;
+ }
+
+ types.put(message.getFullName(), message);
+ }
+
+ private final Set<String> files = new HashSet<String>();
+ private Map<String, Descriptor> types = new HashMap<String, Descriptor>();
+ }
+ }
+
+ /**
+ * An interface for json formatting that can be used in
+ * combination with the omittingInsignificantWhitespace() method
+ */
+ interface TextGenerator {
+ void indent();
+
+ void outdent();
+
+ void print(final CharSequence text) throws IOException;
+ }
+
+ /**
+ * Format the json without indentation
+ */
+ private static final class CompactTextGenerator implements TextGenerator {
+ private final Appendable output;
+
+ private CompactTextGenerator(final Appendable output) {
+ this.output = output;
+ }
+
+ /**
+ * ignored by compact printer
+ */
+ public void indent() {}
+
+ /**
+ * ignored by compact printer
+ */
+ public void outdent() {}
+
+ /**
+ * Print text to the output stream.
+ */
+ public void print(final CharSequence text) throws IOException {
+ output.append(text);
+ }
+ }
+ /**
+ * A TextGenerator adds indentation when writing formatted text.
+ */
+ private static final class PrettyTextGenerator implements TextGenerator {
+ private final Appendable output;
+ private final StringBuilder indent = new StringBuilder();
+ private boolean atStartOfLine = true;
+
+ private PrettyTextGenerator(final Appendable output) {
+ this.output = output;
+ }
+
+ /**
+ * Indent text by two spaces. After calling Indent(), two spaces will be
+ * inserted at the beginning of each line of text. Indent() may be called
+ * multiple times to produce deeper indents.
+ */
+ public void indent() {
+ indent.append(" ");
+ }
+
+ /**
+ * Reduces the current indent level by two spaces, or crashes if the indent
+ * level is zero.
+ */
+ public void outdent() {
+ final int length = indent.length();
+ if (length < 2) {
+ throw new IllegalArgumentException(" Outdent() without matching Indent().");
+ }
+ indent.delete(length - 2, length);
+ }
+
+ /**
+ * Print text to the output stream.
+ */
+ public void print(final CharSequence text) throws IOException {
+ final int size = text.length();
+ int pos = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (text.charAt(i) == '\n') {
+ write(text.subSequence(pos, i + 1));
+ pos = i + 1;
+ atStartOfLine = true;
+ }
+ }
+ write(text.subSequence(pos, size));
+ }
+
+ private void write(final CharSequence data) throws IOException {
+ if (data.length() == 0) {
+ return;
+ }
+ if (atStartOfLine) {
+ atStartOfLine = false;
+ output.append(indent);
+ }
+ output.append(data);
+ }
+ }
+
+ /**
+ * A Printer converts protobuf messages to JSON format.
+ */
+ private static final class PrinterImpl {
+ private final TypeRegistry registry;
+ private final boolean includingDefaultValueFields;
+ private final boolean preservingProtoFieldNames;
+ private final TextGenerator generator;
+ // We use Gson to help handle string escapes.
+ private final Gson gson;
+ private final CharSequence blankOrSpace;
+ private final CharSequence blankOrNewLine;
+
+ private static class GsonHolder {
+ private static final Gson DEFAULT_GSON = new GsonBuilder().disableHtmlEscaping().create();
+ }
+
+ PrinterImpl(
+ TypeRegistry registry,
+ boolean includingDefaultValueFields,
+ boolean preservingProtoFieldNames,
+ Appendable jsonOutput,
+ boolean omittingInsignificantWhitespace) {
+ this.registry = registry;
+ this.includingDefaultValueFields = includingDefaultValueFields;
+ this.preservingProtoFieldNames = preservingProtoFieldNames;
+ this.gson = GsonHolder.DEFAULT_GSON;
+ // json format related properties, determined by printerType
+ if (omittingInsignificantWhitespace) {
+ this.generator = new CompactTextGenerator(jsonOutput);
+ this.blankOrSpace = "";
+ this.blankOrNewLine = "";
+ } else {
+ this.generator = new PrettyTextGenerator(jsonOutput);
+ this.blankOrSpace = " ";
+ this.blankOrNewLine = "\n";
+ }
+ }
+
+ void print(MessageOrBuilder message) throws IOException {
+ WellKnownTypePrinter specialPrinter =
+ wellKnownTypePrinters.get(message.getDescriptorForType().getFullName());
+ if (specialPrinter != null) {
+ specialPrinter.print(this, message);
+ return;
+ }
+ print(message, null);
+ }
+
+ private interface WellKnownTypePrinter {
+ void print(PrinterImpl printer, MessageOrBuilder message) throws IOException;
+ }
+
+ private static final Map<String, WellKnownTypePrinter> wellKnownTypePrinters =
+ buildWellKnownTypePrinters();
+
+ private static Map<String, WellKnownTypePrinter> buildWellKnownTypePrinters() {
+ Map<String, WellKnownTypePrinter> printers = new HashMap<String, WellKnownTypePrinter>();
+ // Special-case Any.
+ printers.put(
+ Any.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printAny(message);
+ }
+ });
+ // Special-case wrapper types.
+ WellKnownTypePrinter wrappersPrinter =
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printWrapper(message);
+ }
+ };
+ printers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+ printers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+ // Special-case Timestamp.
+ printers.put(
+ Timestamp.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printTimestamp(message);
+ }
+ });
+ // Special-case Duration.
+ printers.put(
+ Duration.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printDuration(message);
+ }
+ });
+ // Special-case FieldMask.
+ printers.put(
+ FieldMask.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printFieldMask(message);
+ }
+ });
+ // Special-case Struct.
+ printers.put(
+ Struct.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printStruct(message);
+ }
+ });
+ // Special-case Value.
+ printers.put(
+ Value.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printValue(message);
+ }
+ });
+ // Special-case ListValue.
+ printers.put(
+ ListValue.getDescriptor().getFullName(),
+ new WellKnownTypePrinter() {
+ @Override
+ public void print(PrinterImpl printer, MessageOrBuilder message) throws IOException {
+ printer.printListValue(message);
+ }
+ });
+ return printers;
+ }
+
+ /** Prints google.protobuf.Any */
+ private void printAny(MessageOrBuilder message) throws IOException {
+ if (Any.getDefaultInstance().equals(message)) {
+ generator.print("{}");
+ return;
+ }
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ // Validates type of the message. Note that we can't just cast the message
+ // to com.google.protobuf.Any because it might be a DynamicMessage.
+ if (typeUrlField == null
+ || valueField == null
+ || typeUrlField.getType() != FieldDescriptor.Type.STRING
+ || valueField.getType() != FieldDescriptor.Type.BYTES) {
+ throw new InvalidProtocolBufferException("Invalid Any type.");
+ }
+ String typeUrl = (String) message.getField(typeUrlField);
+ String typeName = getTypeName(typeUrl);
+ Descriptor type = registry.find(typeName);
+ if (type == null) {
+ throw new InvalidProtocolBufferException("Cannot find type for url: " + typeUrl);
+ }
+ ByteString content = (ByteString) message.getField(valueField);
+ Message contentMessage =
+ DynamicMessage.getDefaultInstance(type).getParserForType().parseFrom(content);
+ WellKnownTypePrinter printer = wellKnownTypePrinters.get(typeName);
+ if (printer != null) {
+ // If the type is one of the well-known types, we use a special
+ // formatting.
+ generator.print("{" + blankOrNewLine);
+ generator.indent();
+ generator.print("\"@type\":" + blankOrSpace + gson.toJson(typeUrl) + "," + blankOrNewLine);
+ generator.print("\"value\":" + blankOrSpace);
+ printer.print(this, contentMessage);
+ generator.print(blankOrNewLine);
+ generator.outdent();
+ generator.print("}");
+ } else {
+ // Print the content message instead (with a "@type" field added).
+ print(contentMessage, typeUrl);
+ }
+ }
+
+ /** Prints wrapper types (e.g., google.protobuf.Int32Value) */
+ private void printWrapper(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ if (valueField == null) {
+ throw new InvalidProtocolBufferException("Invalid Wrapper type.");
+ }
+ // When formatting wrapper types, we just print its value field instead of
+ // the whole message.
+ printSingleFieldValue(valueField, message.getField(valueField));
+ }
+
+ private ByteString toByteString(MessageOrBuilder message) {
+ if (message instanceof Message) {
+ return ((Message) message).toByteString();
+ } else {
+ return ((Message.Builder) message).build().toByteString();
+ }
+ }
+
+ /** Prints google.protobuf.Timestamp */
+ private void printTimestamp(MessageOrBuilder message) throws IOException {
+ Timestamp value = Timestamp.parseFrom(toByteString(message));
+ generator.print("\"" + Timestamps.toString(value) + "\"");
+ }
+
+ /** Prints google.protobuf.Duration */
+ private void printDuration(MessageOrBuilder message) throws IOException {
+ Duration value = Duration.parseFrom(toByteString(message));
+ generator.print("\"" + Durations.toString(value) + "\"");
+ }
+
+ /** Prints google.protobuf.FieldMask */
+ private void printFieldMask(MessageOrBuilder message) throws IOException {
+ FieldMask value = FieldMask.parseFrom(toByteString(message));
+ generator.print("\"" + FieldMaskUtil.toJsonString(value) + "\"");
+ }
+
+ /** Prints google.protobuf.Struct */
+ private void printStruct(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("fields");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid Struct type.");
+ }
+ // Struct is formatted as a map object.
+ printMapFieldValue(field, message.getField(field));
+ }
+
+ /** Prints google.protobuf.Value */
+ private void printValue(MessageOrBuilder message) throws IOException {
+ // For a Value message, only the value of the field is formatted.
+ Map<FieldDescriptor, Object> fields = message.getAllFields();
+ if (fields.isEmpty()) {
+ // No value set.
+ generator.print("null");
+ return;
+ }
+ // A Value message can only have at most one field set (it only contains
+ // an oneof).
+ if (fields.size() != 1) {
+ throw new InvalidProtocolBufferException("Invalid Value type.");
+ }
+ for (Map.Entry<FieldDescriptor, Object> entry : fields.entrySet()) {
+ printSingleFieldValue(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /** Prints google.protobuf.ListValue */
+ private void printListValue(MessageOrBuilder message) throws IOException {
+ Descriptor descriptor = message.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("values");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid ListValue type.");
+ }
+ printRepeatedFieldValue(field, message.getField(field));
+ }
+
+ /** Prints a regular message with an optional type URL. */
+ private void print(MessageOrBuilder message, String typeUrl) throws IOException {
+ generator.print("{" + blankOrNewLine);
+ generator.indent();
+
+ boolean printedField = false;
+ if (typeUrl != null) {
+ generator.print("\"@type\":" + blankOrSpace + gson.toJson(typeUrl));
+ printedField = true;
+ }
+ Map<FieldDescriptor, Object> fieldsToPrint = null;
+ if (includingDefaultValueFields) {
+ fieldsToPrint = new TreeMap<FieldDescriptor, Object>();
+ for (FieldDescriptor field : message.getDescriptorForType().getFields()) {
+ if (field.isOptional()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+ && !message.hasField(field)){
+ // Always skip empty optional message fields. If not we will recurse indefinitely if
+ // a message has itself as a sub-field.
+ continue;
+ }
+ OneofDescriptor oneof = field.getContainingOneof();
+ if (oneof != null && !message.hasField(field)) {
+ // Skip all oneof fields except the one that is actually set
+ continue;
+ }
+ }
+ fieldsToPrint.put(field, message.getField(field));
+ }
+ } else {
+ fieldsToPrint = message.getAllFields();
+ }
+ for (Map.Entry<FieldDescriptor, Object> field : fieldsToPrint.entrySet()) {
+ if (printedField) {
+ // Add line-endings for the previous field.
+ generator.print("," + blankOrNewLine);
+ } else {
+ printedField = true;
+ }
+ printField(field.getKey(), field.getValue());
+ }
+
+ // Add line-endings for the last field.
+ if (printedField) {
+ generator.print(blankOrNewLine);
+ }
+ generator.outdent();
+ generator.print("}");
+ }
+
+ private void printField(FieldDescriptor field, Object value) throws IOException {
+ if (preservingProtoFieldNames) {
+ generator.print("\"" + field.getName() + "\":" + blankOrSpace);
+ } else {
+ generator.print("\"" + field.getJsonName() + "\":" + blankOrSpace);
+ }
+ if (field.isMapField()) {
+ printMapFieldValue(field, value);
+ } else if (field.isRepeated()) {
+ printRepeatedFieldValue(field, value);
+ } else {
+ printSingleFieldValue(field, value);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void printRepeatedFieldValue(FieldDescriptor field, Object value) throws IOException {
+ generator.print("[");
+ boolean printedElement = false;
+ for (Object element : (List) value) {
+ if (printedElement) {
+ generator.print("," + blankOrSpace);
+ } else {
+ printedElement = true;
+ }
+ printSingleFieldValue(field, element);
+ }
+ generator.print("]");
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void printMapFieldValue(FieldDescriptor field, Object value) throws IOException {
+ Descriptor type = field.getMessageType();
+ FieldDescriptor keyField = type.findFieldByName("key");
+ FieldDescriptor valueField = type.findFieldByName("value");
+ if (keyField == null || valueField == null) {
+ throw new InvalidProtocolBufferException("Invalid map field.");
+ }
+ generator.print("{" + blankOrNewLine);
+ generator.indent();
+ boolean printedElement = false;
+ for (Object element : (List) value) {
+ Message entry = (Message) element;
+ Object entryKey = entry.getField(keyField);
+ Object entryValue = entry.getField(valueField);
+ if (printedElement) {
+ generator.print("," + blankOrNewLine);
+ } else {
+ printedElement = true;
+ }
+ // Key fields are always double-quoted.
+ printSingleFieldValue(keyField, entryKey, true);
+ generator.print(":" + blankOrSpace);
+ printSingleFieldValue(valueField, entryValue);
+ }
+ if (printedElement) {
+ generator.print(blankOrNewLine);
+ }
+ generator.outdent();
+ generator.print("}");
+ }
+
+ private void printSingleFieldValue(FieldDescriptor field, Object value) throws IOException {
+ printSingleFieldValue(field, value, false);
+ }
+
+ /**
+ * Prints a field's value in JSON format.
+ *
+ * @param alwaysWithQuotes whether to always add double-quotes to primitive
+ * types.
+ */
+ private void printSingleFieldValue(
+ final FieldDescriptor field, final Object value, boolean alwaysWithQuotes)
+ throws IOException {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(((Integer) value).toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ generator.print("\"" + ((Long) value).toString() + "\"");
+ break;
+
+ case BOOL:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ if (((Boolean) value).booleanValue()) {
+ generator.print("true");
+ } else {
+ generator.print("false");
+ }
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case FLOAT:
+ Float floatValue = (Float) value;
+ if (floatValue.isNaN()) {
+ generator.print("\"NaN\"");
+ } else if (floatValue.isInfinite()) {
+ if (floatValue < 0) {
+ generator.print("\"-Infinity\"");
+ } else {
+ generator.print("\"Infinity\"");
+ }
+ } else {
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(floatValue.toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ }
+ break;
+
+ case DOUBLE:
+ Double doubleValue = (Double) value;
+ if (doubleValue.isNaN()) {
+ generator.print("\"NaN\"");
+ } else if (doubleValue.isInfinite()) {
+ if (doubleValue < 0) {
+ generator.print("\"-Infinity\"");
+ } else {
+ generator.print("\"Infinity\"");
+ }
+ } else {
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(doubleValue.toString());
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ }
+ break;
+
+ case UINT32:
+ case FIXED32:
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print(unsignedToString((Integer) value));
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ break;
+
+ case UINT64:
+ case FIXED64:
+ generator.print("\"" + unsignedToString((Long) value) + "\"");
+ break;
+
+ case STRING:
+ generator.print(gson.toJson(value));
+ break;
+
+ case BYTES:
+ generator.print("\"");
+ generator.print(BaseEncoding.base64().encode(((ByteString) value).toByteArray()));
+ generator.print("\"");
+ break;
+
+ case ENUM:
+ // Special-case google.protobuf.NullValue (it's an Enum).
+ if (field.getEnumType().getFullName().equals("google.protobuf.NullValue")) {
+ // No matter what value it contains, we always print it as "null".
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ generator.print("null");
+ if (alwaysWithQuotes) {
+ generator.print("\"");
+ }
+ } else {
+ if (((EnumValueDescriptor) value).getIndex() == -1) {
+ generator.print(String.valueOf(((EnumValueDescriptor) value).getNumber()));
+ } else {
+ generator.print("\"" + ((EnumValueDescriptor) value).getName() + "\"");
+ }
+ }
+ break;
+
+ case MESSAGE:
+ case GROUP:
+ print((Message) value);
+ break;
+ }
+ }
+ }
+
+ /** Convert an unsigned 32-bit integer to a string. */
+ private static String unsignedToString(final int value) {
+ if (value >= 0) {
+ return Integer.toString(value);
+ } else {
+ return Long.toString(value & 0x00000000FFFFFFFFL);
+ }
+ }
+
+ /** Convert an unsigned 64-bit integer to a string. */
+ private static String unsignedToString(final long value) {
+ if (value >= 0) {
+ return Long.toString(value);
+ } else {
+ // Pull off the most-significant bit so that BigInteger doesn't think
+ // the number is negative, then set it again using setBit().
+ return BigInteger.valueOf(value & Long.MAX_VALUE).setBit(Long.SIZE - 1).toString();
+ }
+ }
+
+ private static String getTypeName(String typeUrl) throws InvalidProtocolBufferException {
+ String[] parts = typeUrl.split("/");
+ if (parts.length == 1) {
+ throw new InvalidProtocolBufferException("Invalid type url found: " + typeUrl);
+ }
+ return parts[parts.length - 1];
+ }
+
+ private static class ParserImpl {
+ private final TypeRegistry registry;
+ private final JsonParser jsonParser;
+ private final boolean ignoringUnknownFields;
+ private final int recursionLimit;
+ private int currentDepth;
+
+ ParserImpl(TypeRegistry registry, boolean ignoreUnknownFields, int recursionLimit) {
+ this.registry = registry;
+ this.ignoringUnknownFields = ignoreUnknownFields;
+ this.jsonParser = new JsonParser();
+ this.recursionLimit = recursionLimit;
+ this.currentDepth = 0;
+ }
+
+ void merge(Reader json, Message.Builder builder) throws IOException {
+ try {
+ JsonReader reader = new JsonReader(json);
+ reader.setLenient(false);
+ merge(jsonParser.parse(reader), builder);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (JsonIOException e) {
+ // Unwrap IOException.
+ if (e.getCause() instanceof IOException) {
+ throw (IOException) e.getCause();
+ } else {
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ } catch (Exception e) {
+ // We convert all exceptions from JSON parsing to our own exceptions.
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ }
+
+ void merge(String json, Message.Builder builder) throws InvalidProtocolBufferException {
+ try {
+ JsonReader reader = new JsonReader(new StringReader(json));
+ reader.setLenient(false);
+ merge(jsonParser.parse(reader), builder);
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ // We convert all exceptions from JSON parsing to our own exceptions.
+ throw new InvalidProtocolBufferException(e.getMessage());
+ }
+ }
+
+ private interface WellKnownTypeParser {
+ void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException;
+ }
+
+ private static final Map<String, WellKnownTypeParser> wellKnownTypeParsers =
+ buildWellKnownTypeParsers();
+
+ private static Map<String, WellKnownTypeParser> buildWellKnownTypeParsers() {
+ Map<String, WellKnownTypeParser> parsers = new HashMap<String, WellKnownTypeParser>();
+ // Special-case Any.
+ parsers.put(
+ Any.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeAny(json, builder);
+ }
+ });
+ // Special-case wrapper types.
+ WellKnownTypeParser wrappersPrinter =
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeWrapper(json, builder);
+ }
+ };
+ parsers.put(BoolValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(Int32Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(UInt32Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(Int64Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(UInt64Value.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(StringValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(BytesValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(FloatValue.getDescriptor().getFullName(), wrappersPrinter);
+ parsers.put(DoubleValue.getDescriptor().getFullName(), wrappersPrinter);
+ // Special-case Timestamp.
+ parsers.put(
+ Timestamp.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeTimestamp(json, builder);
+ }
+ });
+ // Special-case Duration.
+ parsers.put(
+ Duration.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeDuration(json, builder);
+ }
+ });
+ // Special-case FieldMask.
+ parsers.put(
+ FieldMask.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeFieldMask(json, builder);
+ }
+ });
+ // Special-case Struct.
+ parsers.put(
+ Struct.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeStruct(json, builder);
+ }
+ });
+ // Special-case ListValue.
+ parsers.put(
+ ListValue.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeListValue(json, builder);
+ }
+ });
+ // Special-case Value.
+ parsers.put(
+ Value.getDescriptor().getFullName(),
+ new WellKnownTypeParser() {
+ @Override
+ public void merge(ParserImpl parser, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ parser.mergeValue(json, builder);
+ }
+ });
+ return parsers;
+ }
+
+ private void merge(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ WellKnownTypeParser specialParser =
+ wellKnownTypeParsers.get(builder.getDescriptorForType().getFullName());
+ if (specialParser != null) {
+ specialParser.merge(this, json, builder);
+ return;
+ }
+ mergeMessage(json, builder, false);
+ }
+
+ // Maps from camel-case field names to FieldDescriptor.
+ private final Map<Descriptor, Map<String, FieldDescriptor>> fieldNameMaps =
+ new HashMap<Descriptor, Map<String, FieldDescriptor>>();
+
+ private Map<String, FieldDescriptor> getFieldNameMap(Descriptor descriptor) {
+ if (!fieldNameMaps.containsKey(descriptor)) {
+ Map<String, FieldDescriptor> fieldNameMap = new HashMap<String, FieldDescriptor>();
+ for (FieldDescriptor field : descriptor.getFields()) {
+ fieldNameMap.put(field.getName(), field);
+ fieldNameMap.put(field.getJsonName(), field);
+ }
+ fieldNameMaps.put(descriptor, fieldNameMap);
+ return fieldNameMap;
+ }
+ return fieldNameMaps.get(descriptor);
+ }
+
+ private void mergeMessage(JsonElement json, Message.Builder builder, boolean skipTypeUrl)
+ throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException("Expect message object but got: " + json);
+ }
+ JsonObject object = (JsonObject) json;
+ Map<String, FieldDescriptor> fieldNameMap = getFieldNameMap(builder.getDescriptorForType());
+ for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+ if (skipTypeUrl && entry.getKey().equals("@type")) {
+ continue;
+ }
+ FieldDescriptor field = fieldNameMap.get(entry.getKey());
+ if (field == null) {
+ if (ignoringUnknownFields) {
+ continue;
+ }
+ throw new InvalidProtocolBufferException(
+ "Cannot find field: "
+ + entry.getKey()
+ + " in message "
+ + builder.getDescriptorForType().getFullName());
+ }
+ mergeField(field, entry.getValue(), builder);
+ }
+ }
+
+ private void mergeAny(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor descriptor = builder.getDescriptorForType();
+ FieldDescriptor typeUrlField = descriptor.findFieldByName("type_url");
+ FieldDescriptor valueField = descriptor.findFieldByName("value");
+ // Validates type of the message. Note that we can't just cast the message
+ // to com.google.protobuf.Any because it might be a DynamicMessage.
+ if (typeUrlField == null
+ || valueField == null
+ || typeUrlField.getType() != FieldDescriptor.Type.STRING
+ || valueField.getType() != FieldDescriptor.Type.BYTES) {
+ throw new InvalidProtocolBufferException("Invalid Any type.");
+ }
+
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException("Expect message object but got: " + json);
+ }
+ JsonObject object = (JsonObject) json;
+ if (object.entrySet().isEmpty()) {
+ return; // builder never modified, so it will end up building the default instance of Any
+ }
+ JsonElement typeUrlElement = object.get("@type");
+ if (typeUrlElement == null) {
+ throw new InvalidProtocolBufferException("Missing type url when parsing: " + json);
+ }
+ String typeUrl = typeUrlElement.getAsString();
+ Descriptor contentType = registry.find(getTypeName(typeUrl));
+ if (contentType == null) {
+ throw new InvalidProtocolBufferException("Cannot resolve type: " + typeUrl);
+ }
+ builder.setField(typeUrlField, typeUrl);
+ Message.Builder contentBuilder =
+ DynamicMessage.getDefaultInstance(contentType).newBuilderForType();
+ WellKnownTypeParser specialParser = wellKnownTypeParsers.get(contentType.getFullName());
+ if (specialParser != null) {
+ JsonElement value = object.get("value");
+ if (value != null) {
+ specialParser.merge(this, value, contentBuilder);
+ }
+ } else {
+ mergeMessage(json, contentBuilder, true);
+ }
+ builder.setField(valueField, contentBuilder.build().toByteString());
+ }
+
+ private void mergeFieldMask(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ FieldMask value = FieldMaskUtil.fromJsonString(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ }
+
+ private void mergeTimestamp(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ try {
+ Timestamp value = Timestamps.parse(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ } catch (ParseException e) {
+ throw new InvalidProtocolBufferException("Failed to parse timestamp: " + json);
+ }
+ }
+
+ private void mergeDuration(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ try {
+ Duration value = Durations.parse(json.getAsString());
+ builder.mergeFrom(value.toByteString());
+ } catch (ParseException e) {
+ throw new InvalidProtocolBufferException("Failed to parse duration: " + json);
+ }
+ }
+
+ private void mergeStruct(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor descriptor = builder.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("fields");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid Struct type.");
+ }
+ mergeMapField(field, json, builder);
+ }
+
+ private void mergeListValue(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor descriptor = builder.getDescriptorForType();
+ FieldDescriptor field = descriptor.findFieldByName("values");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid ListValue type.");
+ }
+ mergeRepeatedField(field, json, builder);
+ }
+
+ private void mergeValue(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor type = builder.getDescriptorForType();
+ if (json instanceof JsonPrimitive) {
+ JsonPrimitive primitive = (JsonPrimitive) json;
+ if (primitive.isBoolean()) {
+ builder.setField(type.findFieldByName("bool_value"), primitive.getAsBoolean());
+ } else if (primitive.isNumber()) {
+ builder.setField(type.findFieldByName("number_value"), primitive.getAsDouble());
+ } else {
+ builder.setField(type.findFieldByName("string_value"), primitive.getAsString());
+ }
+ } else if (json instanceof JsonObject) {
+ FieldDescriptor field = type.findFieldByName("struct_value");
+ Message.Builder structBuilder = builder.newBuilderForField(field);
+ merge(json, structBuilder);
+ builder.setField(field, structBuilder.build());
+ } else if (json instanceof JsonArray) {
+ FieldDescriptor field = type.findFieldByName("list_value");
+ Message.Builder listBuilder = builder.newBuilderForField(field);
+ merge(json, listBuilder);
+ builder.setField(field, listBuilder.build());
+ } else if (json instanceof JsonNull) {
+ builder.setField(
+ type.findFieldByName("null_value"), NullValue.NULL_VALUE.getValueDescriptor());
+ } else {
+ throw new IllegalStateException("Unexpected json data: " + json);
+ }
+ }
+
+ private void mergeWrapper(JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ Descriptor type = builder.getDescriptorForType();
+ FieldDescriptor field = type.findFieldByName("value");
+ if (field == null) {
+ throw new InvalidProtocolBufferException("Invalid wrapper type: " + type.getFullName());
+ }
+ builder.setField(field, parseFieldValue(field, json, builder));
+ }
+
+ private void mergeField(FieldDescriptor field, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ if (field.isRepeated()) {
+ if (builder.getRepeatedFieldCount(field) > 0) {
+ throw new InvalidProtocolBufferException(
+ "Field " + field.getFullName() + " has already been set.");
+ }
+ } else {
+ if (builder.hasField(field)) {
+ throw new InvalidProtocolBufferException(
+ "Field " + field.getFullName() + " has already been set.");
+ }
+ if (field.getContainingOneof() != null
+ && builder.getOneofFieldDescriptor(field.getContainingOneof()) != null) {
+ FieldDescriptor other = builder.getOneofFieldDescriptor(field.getContainingOneof());
+ throw new InvalidProtocolBufferException(
+ "Cannot set field "
+ + field.getFullName()
+ + " because another field "
+ + other.getFullName()
+ + " belonging to the same oneof has already been set ");
+ }
+ }
+ if (field.isRepeated() && json instanceof JsonNull) {
+ // We allow "null" as value for all field types and treat it as if the
+ // field is not present.
+ return;
+ }
+ if (field.isMapField()) {
+ mergeMapField(field, json, builder);
+ } else if (field.isRepeated()) {
+ mergeRepeatedField(field, json, builder);
+ } else {
+ Object value = parseFieldValue(field, json, builder);
+ if (value != null) {
+ builder.setField(field, value);
+ }
+ }
+ }
+
+ private void mergeMapField(FieldDescriptor field, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonObject)) {
+ throw new InvalidProtocolBufferException("Expect a map object but found: " + json);
+ }
+ Descriptor type = field.getMessageType();
+ FieldDescriptor keyField = type.findFieldByName("key");
+ FieldDescriptor valueField = type.findFieldByName("value");
+ if (keyField == null || valueField == null) {
+ throw new InvalidProtocolBufferException("Invalid map field: " + field.getFullName());
+ }
+ JsonObject object = (JsonObject) json;
+ for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+ Message.Builder entryBuilder = builder.newBuilderForField(field);
+ Object key = parseFieldValue(keyField, new JsonPrimitive(entry.getKey()), entryBuilder);
+ Object value = parseFieldValue(valueField, entry.getValue(), entryBuilder);
+ if (value == null) {
+ throw new InvalidProtocolBufferException("Map value cannot be null.");
+ }
+ entryBuilder.setField(keyField, key);
+ entryBuilder.setField(valueField, value);
+ builder.addRepeatedField(field, entryBuilder.build());
+ }
+ }
+
+ /**
+ * Gets the default value for a field type. Note that we use proto3
+ * language defaults and ignore any default values set through the
+ * proto "default" option.
+ */
+ private Object getDefaultValue(FieldDescriptor field, Message.Builder builder) {
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ case UINT32:
+ case FIXED32:
+ return 0;
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ case UINT64:
+ case FIXED64:
+ return 0L;
+ case FLOAT:
+ return 0.0f;
+ case DOUBLE:
+ return 0.0;
+ case BOOL:
+ return false;
+ case STRING:
+ return "";
+ case BYTES:
+ return ByteString.EMPTY;
+ case ENUM:
+ return field.getEnumType().getValues().get(0);
+ case MESSAGE:
+ case GROUP:
+ return builder.newBuilderForField(field).getDefaultInstanceForType();
+ default:
+ throw new IllegalStateException("Invalid field type: " + field.getType());
+ }
+ }
+
+ private void mergeRepeatedField(
+ FieldDescriptor field, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ if (!(json instanceof JsonArray)) {
+ throw new InvalidProtocolBufferException("Expect an array but found: " + json);
+ }
+ JsonArray array = (JsonArray) json;
+ for (int i = 0; i < array.size(); ++i) {
+ Object value = parseFieldValue(field, array.get(i), builder);
+ if (value == null) {
+ throw new InvalidProtocolBufferException("Repeated field elements cannot be null");
+ }
+ builder.addRepeatedField(field, value);
+ }
+ }
+
+ private int parseInt32(JsonElement json) throws InvalidProtocolBufferException {
+ try {
+ return Integer.parseInt(json.getAsString());
+ } catch (Exception e) {
+ // Fall through.
+ }
+ // JSON doesn't distinguish between integer values and floating point values so "1" and
+ // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+ // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+ try {
+ BigDecimal value = new BigDecimal(json.getAsString());
+ return value.intValueExact();
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an int32 value: " + json);
+ }
+ }
+
+ private long parseInt64(JsonElement json) throws InvalidProtocolBufferException {
+ try {
+ return Long.parseLong(json.getAsString());
+ } catch (Exception e) {
+ // Fall through.
+ }
+ // JSON doesn't distinguish between integer values and floating point values so "1" and
+ // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+ // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+ try {
+ BigDecimal value = new BigDecimal(json.getAsString());
+ return value.longValueExact();
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an int32 value: " + json);
+ }
+ }
+
+ private int parseUint32(JsonElement json) throws InvalidProtocolBufferException {
+ try {
+ long result = Long.parseLong(json.getAsString());
+ if (result < 0 || result > 0xFFFFFFFFL) {
+ throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
+ }
+ return (int) result;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ // Fall through.
+ }
+ // JSON doesn't distinguish between integer values and floating point values so "1" and
+ // "1.000" are treated as equal in JSON. For this reason we accept floating point values for
+ // integer fields as well as long as it actually is an integer (i.e., round(value) == value).
+ try {
+ BigDecimal decimalValue = new BigDecimal(json.getAsString());
+ BigInteger value = decimalValue.toBigIntegerExact();
+ if (value.signum() < 0 || value.compareTo(new BigInteger("FFFFFFFF", 16)) > 0) {
+ throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
+ }
+ return value.intValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an uint32 value: " + json);
+ }
+ }
+
+ private static final BigInteger MAX_UINT64 = new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+ private long parseUint64(JsonElement json) throws InvalidProtocolBufferException {
+ try {
+ BigDecimal decimalValue = new BigDecimal(json.getAsString());
+ BigInteger value = decimalValue.toBigIntegerExact();
+ if (value.compareTo(BigInteger.ZERO) < 0 || value.compareTo(MAX_UINT64) > 0) {
+ throw new InvalidProtocolBufferException("Out of range uint64 value: " + json);
+ }
+ return value.longValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an uint64 value: " + json);
+ }
+ }
+
+ private boolean parseBool(JsonElement json) throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("true")) {
+ return true;
+ }
+ if (json.getAsString().equals("false")) {
+ return false;
+ }
+ throw new InvalidProtocolBufferException("Invalid bool value: " + json);
+ }
+
+ private static final double EPSILON = 1e-6;
+
+ private float parseFloat(JsonElement json) throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("NaN")) {
+ return Float.NaN;
+ } else if (json.getAsString().equals("Infinity")) {
+ return Float.POSITIVE_INFINITY;
+ } else if (json.getAsString().equals("-Infinity")) {
+ return Float.NEGATIVE_INFINITY;
+ }
+ try {
+ // We don't use Float.parseFloat() here because that function simply
+ // accepts all double values. Here we parse the value into a Double
+ // and do explicit range check on it.
+ double value = Double.parseDouble(json.getAsString());
+ // When a float value is printed, the printed value might be a little
+ // larger or smaller due to precision loss. Here we need to add a bit
+ // of tolerance when checking whether the float value is in range.
+ if (value > Float.MAX_VALUE * (1.0 + EPSILON)
+ || value < -Float.MAX_VALUE * (1.0 + EPSILON)) {
+ throw new InvalidProtocolBufferException("Out of range float value: " + json);
+ }
+ return (float) value;
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not a float value: " + json);
+ }
+ }
+
+ private static final BigDecimal MORE_THAN_ONE = new BigDecimal(String.valueOf(1.0 + EPSILON));
+ // When a float value is printed, the printed value might be a little
+ // larger or smaller due to precision loss. Here we need to add a bit
+ // of tolerance when checking whether the float value is in range.
+ private static final BigDecimal MAX_DOUBLE =
+ new BigDecimal(String.valueOf(Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+ private static final BigDecimal MIN_DOUBLE =
+ new BigDecimal(String.valueOf(-Double.MAX_VALUE)).multiply(MORE_THAN_ONE);
+
+ private double parseDouble(JsonElement json) throws InvalidProtocolBufferException {
+ if (json.getAsString().equals("NaN")) {
+ return Double.NaN;
+ } else if (json.getAsString().equals("Infinity")) {
+ return Double.POSITIVE_INFINITY;
+ } else if (json.getAsString().equals("-Infinity")) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ try {
+ // We don't use Double.parseDouble() here because that function simply
+ // accepts all values. Here we parse the value into a BigDecimal and do
+ // explicit range check on it.
+ BigDecimal value = new BigDecimal(json.getAsString());
+ if (value.compareTo(MAX_DOUBLE) > 0 || value.compareTo(MIN_DOUBLE) < 0) {
+ throw new InvalidProtocolBufferException("Out of range double value: " + json);
+ }
+ return value.doubleValue();
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidProtocolBufferException("Not an double value: " + json);
+ }
+ }
+
+ private String parseString(JsonElement json) {
+ return json.getAsString();
+ }
+
+ private ByteString parseBytes(JsonElement json) throws InvalidProtocolBufferException {
+ return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
+ }
+
+ private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement json)
+ throws InvalidProtocolBufferException {
+ String value = json.getAsString();
+ EnumValueDescriptor result = enumDescriptor.findValueByName(value);
+ if (result == null) {
+ // Try to interpret the value as a number.
+ try {
+ int numericValue = parseInt32(json);
+ if (enumDescriptor.getFile().getSyntax() == FileDescriptor.Syntax.PROTO3) {
+ result = enumDescriptor.findValueByNumberCreatingIfUnknown(numericValue);
+ } else {
+ result = enumDescriptor.findValueByNumber(numericValue);
+ }
+ } catch (InvalidProtocolBufferException e) {
+ // Fall through. This exception is about invalid int32 value we get from parseInt32() but
+ // that's not the exception we want the user to see. Since result == null, we will throw
+ // an exception later.
+ }
+
+ if (result == null) {
+ throw new InvalidProtocolBufferException(
+ "Invalid enum value: " + value + " for enum type: " + enumDescriptor.getFullName());
+ }
+ }
+ return result;
+ }
+
+ private Object parseFieldValue(FieldDescriptor field, JsonElement json, Message.Builder builder)
+ throws InvalidProtocolBufferException {
+ if (json instanceof JsonNull) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+ && field.getMessageType().getFullName().equals(Value.getDescriptor().getFullName())) {
+ // For every other type, "null" means absence, but for the special
+ // Value message, it means the "null_value" field has been set.
+ Value value = Value.newBuilder().setNullValueValue(0).build();
+ return builder.newBuilderForField(field).mergeFrom(value.toByteString()).build();
+ } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM
+ && field.getEnumType().getFullName().equals(NullValue.getDescriptor().getFullName())) {
+ // If the type of the field is a NullValue, then the value should be explicitly set.
+ return field.getEnumType().findValueByNumber(0);
+ }
+ return null;
+ }
+ switch (field.getType()) {
+ case INT32:
+ case SINT32:
+ case SFIXED32:
+ return parseInt32(json);
+
+ case INT64:
+ case SINT64:
+ case SFIXED64:
+ return parseInt64(json);
+
+ case BOOL:
+ return parseBool(json);
+
+ case FLOAT:
+ return parseFloat(json);
+
+ case DOUBLE:
+ return parseDouble(json);
+
+ case UINT32:
+ case FIXED32:
+ return parseUint32(json);
+
+ case UINT64:
+ case FIXED64:
+ return parseUint64(json);
+
+ case STRING:
+ return parseString(json);
+
+ case BYTES:
+ return parseBytes(json);
+
+ case ENUM:
+ return parseEnum(field.getEnumType(), json);
+
+ case MESSAGE:
+ case GROUP:
+ if (currentDepth >= recursionLimit) {
+ throw new InvalidProtocolBufferException("Hit recursion limit.");
+ }
+ ++currentDepth;
+ Message.Builder subBuilder = builder.newBuilderForField(field);
+ merge(json, subBuilder);
+ --currentDepth;
+ return subBuilder.build();
+
+ default:
+ throw new InvalidProtocolBufferException("Invalid field type: " + field.getType());
+ }
+ }
+ }
+}
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
new file mode 100644
index 0000000000..0475847349
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/TimeUtil.java
@@ -0,0 +1,400 @@
+// 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.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+
+import java.math.BigInteger;
+import java.text.ParseException;
+
+/**
+ * Utilities to help create/manipulate Timestamp/Duration
+ *
+ * @deprecated Use {@link Durations} and {@link Timestamps} instead.
+ */
+@Deprecated
+public final class TimeUtil {
+ // Timestamp for "0001-01-01T00:00:00Z"
+ public static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
+
+ // Timestamp for "9999-12-31T23:59:59Z"
+ public static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
+ public static final long DURATION_SECONDS_MIN = -315576000000L;
+ public static final long DURATION_SECONDS_MAX = 315576000000L;
+
+ private static final long NANOS_PER_SECOND = 1000000000;
+
+ private TimeUtil() {}
+
+ /**
+ * Convert Timestamp to RFC 3339 date string format. The output will always
+ * be Z-normalized and uses 3, 6 or 9 fractional digits as required to
+ * represent the exact value. Note that Timestamp can only represent time
+ * from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
+ * https://www.ietf.org/rfc/rfc3339.txt
+ *
+ * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
+ *
+ * @return The string representation of the given timestamp.
+ * @throws IllegalArgumentException if the given timestamp is not in the
+ * valid range.
+ * @deprecated Use {@link Timestamps#toString} instead.
+ */
+ @Deprecated
+ public static String toString(Timestamp timestamp) {
+ return Timestamps.toString(timestamp);
+ }
+
+ /**
+ * Parse from RFC 3339 date string to Timestamp. This method accepts all
+ * outputs of {@link #toString(Timestamp)} and it also accepts any fractional
+ * digits (or none) and any offset as long as they fit into nano-seconds
+ * precision.
+ *
+ * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
+ *
+ * @return A Timestamp parsed from the string.
+ * @throws ParseException if parsing fails.
+ * @deprecated Use {@link Timestamps#parse} instead.
+ */
+ @Deprecated
+ public static Timestamp parseTimestamp(String value) throws ParseException {
+ return Timestamps.parse(value);
+ }
+
+ /**
+ * Convert Duration to string format. The string format will contains 3, 6,
+ * or 9 fractional digits depending on the precision required to represent
+ * the exact Duration value. For example: "1s", "1.010s", "1.000000100s",
+ * "-3.100s" The range that can be represented by Duration is from
+ * -315,576,000,000 to +315,576,000,000 inclusive (in seconds).
+ *
+ * @return The string representation of the given duration.
+ * @throws IllegalArgumentException if the given duration is not in the valid
+ * range.
+ * @deprecated Use {@link Durations#toString} instead.
+ */
+ @Deprecated
+ public static String toString(Duration duration) {
+ return Durations.toString(duration);
+ }
+
+ /**
+ * Parse from a string to produce a duration.
+ *
+ * @return A Duration parsed from the string.
+ * @throws ParseException if parsing fails.
+ * @deprecated Use {@link Durations#parse} instead.
+ */
+ @Deprecated
+ public static Duration parseDuration(String value) throws ParseException {
+ return Durations.parse(value);
+ }
+
+ /**
+ * Create a Timestamp from the number of milliseconds elapsed from the epoch.
+ *
+ * @deprecated Use {@link Timestamps#fromMillis} instead.
+ */
+ @Deprecated
+ public static Timestamp createTimestampFromMillis(long milliseconds) {
+ return Timestamps.fromMillis(milliseconds);
+ }
+
+ /**
+ * Create a Duration from the number of milliseconds.
+ *
+ * @deprecated Use {@link Durations#fromMillis} instead.
+ */
+ @Deprecated
+ public static Duration createDurationFromMillis(long milliseconds) {
+ return Durations.fromMillis(milliseconds);
+ }
+
+ /**
+ * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest millisecond. E.g., if the
+ * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+ * to -1 millisecond.
+ *
+ * @deprecated Use {@link Timestamps#toMillis} instead.
+ */
+ @Deprecated
+ public static long toMillis(Timestamp timestamp) {
+ return Timestamps.toMillis(timestamp);
+ }
+
+ /**
+ * Convert a Duration to the number of milliseconds.The result will be
+ * rounded towards 0 to the nearest millisecond. E.g., if the duration
+ * represents -1 nanosecond, it will be rounded to 0.
+ *
+ * @deprecated Use {@link Durations#toMillis} instead.
+ */
+ @Deprecated
+ public static long toMillis(Duration duration) {
+ return Durations.toMillis(duration);
+ }
+
+ /**
+ * Create a Timestamp from the number of microseconds elapsed from the epoch.
+ *
+ * @deprecated Use {@link Timestamps#fromMicros} instead.
+ */
+ @Deprecated
+ public static Timestamp createTimestampFromMicros(long microseconds) {
+ return Timestamps.fromMicros(microseconds);
+ }
+
+ /**
+ * Create a Duration from the number of microseconds.
+ *
+ * @deprecated Use {@link Durations#fromMicros} instead.
+ */
+ @Deprecated
+ public static Duration createDurationFromMicros(long microseconds) {
+ return Durations.fromMicros(microseconds);
+ }
+
+ /**
+ * Convert a Timestamp to the number of microseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest microsecond. E.g., if the
+ * timestamp represents "1969-12-31T23:59:59.999999999Z", it will be rounded
+ * to -1 millisecond.
+ *
+ * @deprecated Use {@link Timestamps#toMicros} instead.
+ */
+ @Deprecated
+ public static long toMicros(Timestamp timestamp) {
+ return Timestamps.toMicros(timestamp);
+ }
+
+ /**
+ * Convert a Duration to the number of microseconds.The result will be
+ * rounded towards 0 to the nearest microseconds. E.g., if the duration
+ * represents -1 nanosecond, it will be rounded to 0.
+ *
+ * @deprecated Use {@link Durations#toMicros} instead.
+ */
+ @Deprecated
+ public static long toMicros(Duration duration) {
+ return Durations.toMicros(duration);
+ }
+
+ /**
+ * Create a Timestamp from the number of nanoseconds elapsed from the epoch.
+ *
+ * @deprecated Use {@link Timestamps#fromNanos} instead.
+ */
+ @Deprecated
+ public static Timestamp createTimestampFromNanos(long nanoseconds) {
+ return Timestamps.fromNanos(nanoseconds);
+ }
+
+ /**
+ * Create a Duration from the number of nanoseconds.
+ *
+ * @deprecated Use {@link Durations#fromNanos} instead.
+ */
+ @Deprecated
+ public static Duration createDurationFromNanos(long nanoseconds) {
+ return Durations.fromNanos(nanoseconds);
+ }
+
+ /**
+ * Convert a Timestamp to the number of nanoseconds elapsed from the epoch.
+ *
+ * @deprecated Use {@link Timestamps#toNanos} instead.
+ */
+ @Deprecated
+ public static long toNanos(Timestamp timestamp) {
+ return Timestamps.toNanos(timestamp);
+ }
+
+ /**
+ * Convert a Duration to the number of nanoseconds.
+ *
+ * @deprecated Use {@link Durations#toNanos} instead.
+ */
+ @Deprecated
+ public static long toNanos(Duration duration) {
+ return Durations.toNanos(duration);
+ }
+
+ /**
+ * Get the current time.
+ *
+ * @deprecated Use {@code Timestamps.fromMillis(System.currentTimeMillis())} instead.
+ */
+ @Deprecated
+ public static Timestamp getCurrentTime() {
+ return Timestamps.fromMillis(System.currentTimeMillis());
+ }
+
+ /**
+ * Get the epoch.
+ *
+ * @deprecated Use {@code Timestamps.fromMillis(0)} instead.
+ */
+ @Deprecated
+ public static Timestamp getEpoch() {
+ return Timestamp.getDefaultInstance();
+ }
+
+ /**
+ * Calculate the difference between two timestamps.
+ *
+ * @deprecated Use {@link Timestamps#between} instead.
+ */
+ @Deprecated
+ public static Duration distance(Timestamp from, Timestamp to) {
+ return Timestamps.between(from, to);
+ }
+
+ /**
+ * Add a duration to a timestamp.
+ *
+ * @deprecated Use {@link Timestamps#add} instead.
+ */
+ @Deprecated
+ public static Timestamp add(Timestamp start, Duration length) {
+ return Timestamps.add(start, length);
+ }
+
+ /**
+ * Subtract a duration from a timestamp.
+ *
+ * @deprecated Use {@link Timestamps#subtract} instead.
+ */
+ @Deprecated
+ public static Timestamp subtract(Timestamp start, Duration length) {
+ return Timestamps.subtract(start, length);
+ }
+
+ /**
+ * Add two durations.
+ *
+ * @deprecated Use {@link Durations#add} instead.
+ */
+ @Deprecated
+ public static Duration add(Duration d1, Duration d2) {
+ return Durations.add(d1, d2);
+ }
+
+ /**
+ * Subtract a duration from another.
+ *
+ * @deprecated Use {@link Durations#subtract} instead.
+ */
+ @Deprecated
+ public static Duration subtract(Duration d1, Duration d2) {
+ return Durations.subtract(d1, d2);
+ }
+
+ // Multiplications and divisions.
+
+ // TODO(kak): Delete this.
+ public static Duration multiply(Duration duration, double times) {
+ double result = duration.getSeconds() * times + duration.getNanos() * times / 1000000000.0;
+ if (result < Long.MIN_VALUE || result > Long.MAX_VALUE) {
+ throw new IllegalArgumentException("Result is out of valid range.");
+ }
+ long seconds = (long) result;
+ int nanos = (int) ((result - seconds) * 1000000000);
+ return normalizedDuration(seconds, nanos);
+ }
+
+ // TODO(kak): Delete this.
+ public static Duration divide(Duration duration, double value) {
+ return multiply(duration, 1.0 / value);
+ }
+
+ // TODO(kak): Delete this.
+ public static Duration multiply(Duration duration, long times) {
+ return createDurationFromBigInteger(toBigInteger(duration).multiply(toBigInteger(times)));
+ }
+
+ // TODO(kak): Delete this.
+ public static Duration divide(Duration duration, long times) {
+ return createDurationFromBigInteger(toBigInteger(duration).divide(toBigInteger(times)));
+ }
+
+ // TODO(kak): Delete this.
+ public static long divide(Duration d1, Duration d2) {
+ return toBigInteger(d1).divide(toBigInteger(d2)).longValue();
+ }
+
+ // TODO(kak): Delete this.
+ public static Duration remainder(Duration d1, Duration d2) {
+ return createDurationFromBigInteger(toBigInteger(d1).remainder(toBigInteger(d2)));
+ }
+
+ private static final BigInteger NANOS_PER_SECOND_BIG_INTEGER =
+ new BigInteger(String.valueOf(NANOS_PER_SECOND));
+
+ private static BigInteger toBigInteger(Duration duration) {
+ return toBigInteger(duration.getSeconds())
+ .multiply(NANOS_PER_SECOND_BIG_INTEGER)
+ .add(toBigInteger(duration.getNanos()));
+ }
+
+ private static BigInteger toBigInteger(long value) {
+ return new BigInteger(String.valueOf(value));
+ }
+
+ private static Duration createDurationFromBigInteger(BigInteger value) {
+ long seconds = value.divide(new BigInteger(String.valueOf(NANOS_PER_SECOND))).longValue();
+ int nanos = value.remainder(new BigInteger(String.valueOf(NANOS_PER_SECOND))).intValue();
+ return normalizedDuration(seconds, nanos);
+ }
+
+ private static Duration normalizedDuration(long seconds, int nanos) {
+ if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+ seconds += nanos / NANOS_PER_SECOND;
+ nanos %= NANOS_PER_SECOND;
+ }
+ if (seconds > 0 && nanos < 0) {
+ nanos += NANOS_PER_SECOND;
+ seconds -= 1;
+ }
+ if (seconds < 0 && nanos > 0) {
+ nanos -= NANOS_PER_SECOND;
+ seconds += 1;
+ }
+ if (seconds < DURATION_SECONDS_MIN || seconds > DURATION_SECONDS_MAX) {
+ throw new IllegalArgumentException("Duration is out of valid range.");
+ }
+ return Duration.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+ }
+}
diff --git a/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
new file mode 100644
index 0000000000..1d631a2c58
--- /dev/null
+++ b/third_party/protobuf/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
@@ -0,0 +1,397 @@
+// 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.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.math.IntMath.checkedAdd;
+import static com.google.common.math.IntMath.checkedSubtract;
+import static com.google.common.math.LongMath.checkedAdd;
+import static com.google.common.math.LongMath.checkedMultiply;
+import static com.google.common.math.LongMath.checkedSubtract;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Utilities to help create/manipulate {@code protobuf/timestamp.proto}. All operations throw an
+ * {@link IllegalArgumentException} if the input(s) are not {@linkplain #isValid(Timestamp) valid}.
+ */
+public final class Timestamps {
+
+ // Timestamp for "0001-01-01T00:00:00Z"
+ static final long TIMESTAMP_SECONDS_MIN = -62135596800L;
+
+ // Timestamp for "9999-12-31T23:59:59Z"
+ static final long TIMESTAMP_SECONDS_MAX = 253402300799L;
+
+ static final long NANOS_PER_SECOND = 1000000000;
+ static final long NANOS_PER_MILLISECOND = 1000000;
+ static final long NANOS_PER_MICROSECOND = 1000;
+ static final long MILLIS_PER_SECOND = 1000;
+ static final long MICROS_PER_SECOND = 1000000;
+
+ /** A constant holding the minimum valid {@link Timestamp}, {@code 0001-01-01T00:00:00Z}. */
+ public static final Timestamp MIN_VALUE =
+ Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MIN).setNanos(0).build();
+
+ /**
+ * A constant holding the maximum valid {@link Timestamp}, {@code 9999-12-31T23:59:59.999999999Z}.
+ */
+ public static final Timestamp MAX_VALUE =
+ Timestamp.newBuilder().setSeconds(TIMESTAMP_SECONDS_MAX).setNanos(999999999).build();
+
+ private static final ThreadLocal<SimpleDateFormat> timestampFormat =
+ new ThreadLocal<SimpleDateFormat>() {
+ @Override
+ protected SimpleDateFormat initialValue() {
+ return createTimestampFormat();
+ }
+ };
+
+ private static SimpleDateFormat createTimestampFormat() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH);
+ GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ // We use Proleptic Gregorian Calendar (i.e., Gregorian calendar extends
+ // backwards to year one) for timestamp formating.
+ calendar.setGregorianChange(new Date(Long.MIN_VALUE));
+ sdf.setCalendar(calendar);
+ return sdf;
+ }
+
+ private Timestamps() {}
+
+ private static final Comparator<Timestamp> COMPARATOR =
+ new Comparator<Timestamp>() {
+ @Override
+ public int compare(Timestamp t1, Timestamp t2) {
+ checkValid(t1);
+ checkValid(t2);
+ int secDiff = Long.compare(t1.getSeconds(), t2.getSeconds());
+ return (secDiff != 0) ? secDiff : Integer.compare(t1.getNanos(), t2.getNanos());
+ }
+ };
+
+ /**
+ * Returns a {@link Comparator} for {@link Timestamp}s which sorts in increasing chronological
+ * order. Nulls and invalid {@link Timestamp}s are not allowed (see {@link #isValid}).
+ */
+ public static Comparator<Timestamp> comparator() {
+ return COMPARATOR;
+ }
+
+ /**
+ * Returns true if the given {@link Timestamp} is valid. The {@code seconds} value must be in the
+ * range [-62,135,596,800, +253,402,300,799] (i.e., between 0001-01-01T00:00:00Z and
+ * 9999-12-31T23:59:59Z). The {@code nanos} value must be in the range [0, +999,999,999].
+ *
+ * <p><b>Note:</b> Negative second values with fractional seconds must still have non-negative
+ * nanos values that count forward in time.
+ */
+ public static boolean isValid(Timestamp timestamp) {
+ return isValid(timestamp.getSeconds(), timestamp.getNanos());
+ }
+
+ /**
+ * Returns true if the given number of seconds and nanos is a valid {@link Timestamp}. The {@code
+ * seconds} value must be in the range [-62,135,596,800, +253,402,300,799] (i.e., between
+ * 0001-01-01T00:00:00Z and 9999-12-31T23:59:59Z). The {@code nanos} value must be in the range
+ * [0, +999,999,999].
+ *
+ * <p><b>Note:</b> Negative second values with fractional seconds must still have non-negative
+ * nanos values that count forward in time.
+ */
+ public static boolean isValid(long seconds, int nanos) {
+ if (seconds < TIMESTAMP_SECONDS_MIN || seconds > TIMESTAMP_SECONDS_MAX) {
+ return false;
+ }
+ if (nanos < 0 || nanos >= NANOS_PER_SECOND) {
+ return false;
+ }
+ return true;
+ }
+
+ /** Throws an {@link IllegalArgumentException} if the given {@link Timestamp} is not valid. */
+ public static Timestamp checkValid(Timestamp timestamp) {
+ long seconds = timestamp.getSeconds();
+ int nanos = timestamp.getNanos();
+ checkArgument(
+ isValid(seconds, nanos),
+ "Timestamp is not valid. See proto definition for valid values. "
+ + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. "
+ + "Nanos (%s) must be in range [0, +999,999,999].",
+ seconds,
+ nanos);
+ return timestamp;
+ }
+
+ /**
+ * Convert Timestamp to RFC 3339 date string format. The output will always be Z-normalized and
+ * uses 3, 6 or 9 fractional digits as required to represent the exact value. Note that Timestamp
+ * can only represent time from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. See
+ * https://www.ietf.org/rfc/rfc3339.txt
+ *
+ * <p>Example of generated format: "1972-01-01T10:00:20.021Z"
+ *
+ * @return The string representation of the given timestamp.
+ * @throws IllegalArgumentException if the given timestamp is not in the valid range.
+ */
+ public static String toString(Timestamp timestamp) {
+ checkValid(timestamp);
+
+ long seconds = timestamp.getSeconds();
+ int nanos = timestamp.getNanos();
+
+ StringBuilder result = new StringBuilder();
+ // Format the seconds part.
+ Date date = new Date(seconds * MILLIS_PER_SECOND);
+ result.append(timestampFormat.get().format(date));
+ // Format the nanos part.
+ if (nanos != 0) {
+ result.append(".");
+ result.append(formatNanos(nanos));
+ }
+ result.append("Z");
+ return result.toString();
+ }
+
+ /**
+ * Parse from RFC 3339 date string to Timestamp. This method accepts all outputs of {@link
+ * #toString(Timestamp)} and it also accepts any fractional digits (or none) and any offset as
+ * long as they fit into nano-seconds precision.
+ *
+ * <p>Example of accepted format: "1972-01-01T10:00:20.021-05:00"
+ *
+ * @return A Timestamp parsed from the string.
+ * @throws ParseException if parsing fails.
+ */
+ public static Timestamp parse(String value) throws ParseException {
+ int dayOffset = value.indexOf('T');
+ if (dayOffset == -1) {
+ throw new ParseException("Failed to parse timestamp: invalid timestamp \"" + value + "\"", 0);
+ }
+ int timezoneOffsetPosition = value.indexOf('Z', dayOffset);
+ if (timezoneOffsetPosition == -1) {
+ timezoneOffsetPosition = value.indexOf('+', dayOffset);
+ }
+ if (timezoneOffsetPosition == -1) {
+ timezoneOffsetPosition = value.indexOf('-', dayOffset);
+ }
+ if (timezoneOffsetPosition == -1) {
+ throw new ParseException("Failed to parse timestamp: missing valid timezone offset.", 0);
+ }
+ // Parse seconds and nanos.
+ String timeValue = value.substring(0, timezoneOffsetPosition);
+ String secondValue = timeValue;
+ String nanoValue = "";
+ int pointPosition = timeValue.indexOf('.');
+ if (pointPosition != -1) {
+ secondValue = timeValue.substring(0, pointPosition);
+ nanoValue = timeValue.substring(pointPosition + 1);
+ }
+ Date date = timestampFormat.get().parse(secondValue);
+ long seconds = date.getTime() / MILLIS_PER_SECOND;
+ int nanos = nanoValue.isEmpty() ? 0 : parseNanos(nanoValue);
+ // Parse timezone offsets.
+ if (value.charAt(timezoneOffsetPosition) == 'Z') {
+ if (value.length() != timezoneOffsetPosition + 1) {
+ throw new ParseException(
+ "Failed to parse timestamp: invalid trailing data \""
+ + value.substring(timezoneOffsetPosition)
+ + "\"",
+ 0);
+ }
+ } else {
+ String offsetValue = value.substring(timezoneOffsetPosition + 1);
+ long offset = parseTimezoneOffset(offsetValue);
+ if (value.charAt(timezoneOffsetPosition) == '+') {
+ seconds -= offset;
+ } else {
+ seconds += offset;
+ }
+ }
+ try {
+ return normalizedTimestamp(seconds, nanos);
+ } catch (IllegalArgumentException e) {
+ throw new ParseException("Failed to parse timestamp: timestamp is out of range.", 0);
+ }
+ }
+
+ /** Create a Timestamp from the number of seconds elapsed from the epoch. */
+ public static Timestamp fromSeconds(long seconds) {
+ return normalizedTimestamp(seconds, 0);
+ }
+
+ /**
+ * Convert a Timestamp to the number of seconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest second. E.g., if the timestamp represents
+ * "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 second.
+ */
+ public static long toSeconds(Timestamp timestamp) {
+ return checkValid(timestamp).getSeconds();
+ }
+
+ /** Create a Timestamp from the number of milliseconds elapsed from the epoch. */
+ public static Timestamp fromMillis(long milliseconds) {
+ return normalizedTimestamp(
+ milliseconds / MILLIS_PER_SECOND,
+ (int) (milliseconds % MILLIS_PER_SECOND * NANOS_PER_MILLISECOND));
+ }
+
+ /**
+ * Convert a Timestamp to the number of milliseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest millisecond. E.g., if the timestamp
+ * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond.
+ */
+ public static long toMillis(Timestamp timestamp) {
+ checkValid(timestamp);
+ return checkedAdd(
+ checkedMultiply(timestamp.getSeconds(), MILLIS_PER_SECOND),
+ timestamp.getNanos() / NANOS_PER_MILLISECOND);
+ }
+
+ /** Create a Timestamp from the number of microseconds elapsed from the epoch. */
+ public static Timestamp fromMicros(long microseconds) {
+ return normalizedTimestamp(
+ microseconds / MICROS_PER_SECOND,
+ (int) (microseconds % MICROS_PER_SECOND * NANOS_PER_MICROSECOND));
+ }
+
+ /**
+ * Convert a Timestamp to the number of microseconds elapsed from the epoch.
+ *
+ * <p>The result will be rounded down to the nearest microsecond. E.g., if the timestamp
+ * represents "1969-12-31T23:59:59.999999999Z", it will be rounded to -1 millisecond.
+ */
+ public static long toMicros(Timestamp timestamp) {
+ checkValid(timestamp);
+ return checkedAdd(
+ checkedMultiply(timestamp.getSeconds(), MICROS_PER_SECOND),
+ timestamp.getNanos() / NANOS_PER_MICROSECOND);
+ }
+
+ /** Create a Timestamp from the number of nanoseconds elapsed from the epoch. */
+ public static Timestamp fromNanos(long nanoseconds) {
+ return normalizedTimestamp(
+ nanoseconds / NANOS_PER_SECOND, (int) (nanoseconds % NANOS_PER_SECOND));
+ }
+
+ /** Convert a Timestamp to the number of nanoseconds elapsed from the epoch. */
+ public static long toNanos(Timestamp timestamp) {
+ checkValid(timestamp);
+ return checkedAdd(
+ checkedMultiply(timestamp.getSeconds(), NANOS_PER_SECOND), timestamp.getNanos());
+ }
+
+ /** Calculate the difference between two timestamps. */
+ public static Duration between(Timestamp from, Timestamp to) {
+ checkValid(from);
+ checkValid(to);
+ return Durations.normalizedDuration(
+ checkedSubtract(to.getSeconds(), from.getSeconds()),
+ checkedSubtract(to.getNanos(), from.getNanos()));
+ }
+
+ /** Add a duration to a timestamp. */
+ public static Timestamp add(Timestamp start, Duration length) {
+ checkValid(start);
+ Durations.checkValid(length);
+ return normalizedTimestamp(
+ checkedAdd(start.getSeconds(), length.getSeconds()),
+ checkedAdd(start.getNanos(), length.getNanos()));
+ }
+
+ /** Subtract a duration from a timestamp. */
+ public static Timestamp subtract(Timestamp start, Duration length) {
+ checkValid(start);
+ Durations.checkValid(length);
+ return normalizedTimestamp(
+ checkedSubtract(start.getSeconds(), length.getSeconds()),
+ checkedSubtract(start.getNanos(), length.getNanos()));
+ }
+
+ static Timestamp normalizedTimestamp(long seconds, int nanos) {
+ if (nanos <= -NANOS_PER_SECOND || nanos >= NANOS_PER_SECOND) {
+ seconds = checkedAdd(seconds, nanos / NANOS_PER_SECOND);
+ nanos %= NANOS_PER_SECOND;
+ }
+ if (nanos < 0) {
+ nanos += NANOS_PER_SECOND; // no overflow since nanos is negative (and we're adding)
+ seconds = checkedSubtract(seconds, 1);
+ }
+ Timestamp timestamp = Timestamp.newBuilder().setSeconds(seconds).setNanos(nanos).build();
+ return checkValid(timestamp);
+ }
+
+ private static long parseTimezoneOffset(String value) throws ParseException {
+ int pos = value.indexOf(':');
+ if (pos == -1) {
+ throw new ParseException("Invalid offset value: " + value, 0);
+ }
+ String hours = value.substring(0, pos);
+ String minutes = value.substring(pos + 1);
+ return (Long.parseLong(hours) * 60 + Long.parseLong(minutes)) * 60;
+ }
+
+ static int parseNanos(String value) throws ParseException {
+ int result = 0;
+ for (int i = 0; i < 9; ++i) {
+ result = result * 10;
+ if (i < value.length()) {
+ if (value.charAt(i) < '0' || value.charAt(i) > '9') {
+ throw new ParseException("Invalid nanoseconds.", 0);
+ }
+ result += value.charAt(i) - '0';
+ }
+ }
+ return result;
+ }
+
+ /** Format the nano part of a timestamp or a duration. */
+ static String formatNanos(int nanos) {
+ // Determine whether to use 3, 6, or 9 digits for the nano part.
+ if (nanos % NANOS_PER_MILLISECOND == 0) {
+ return String.format(Locale.ENGLISH, "%1$03d", nanos / NANOS_PER_MILLISECOND);
+ } else if (nanos % NANOS_PER_MICROSECOND == 0) {
+ return String.format(Locale.ENGLISH, "%1$06d", nanos / NANOS_PER_MICROSECOND);
+ } else {
+ return String.format(Locale.ENGLISH, "%1$09d", nanos);
+ }
+ }
+}
diff --git a/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
new file mode 100644
index 0000000000..3ee0fc6e6a
--- /dev/null
+++ b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskTreeTest.java
@@ -0,0 +1,261 @@
+// 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.util;
+
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
+
+import junit.framework.TestCase;
+
+public class FieldMaskTreeTest extends TestCase {
+ public void testAddFieldPath() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree();
+ assertEquals("", tree.toString());
+ tree.addFieldPath("");
+ assertEquals("", tree.toString());
+ // New branch.
+ tree.addFieldPath("foo");
+ assertEquals("foo", tree.toString());
+ // Redundant path.
+ tree.addFieldPath("foo");
+ assertEquals("foo", tree.toString());
+ // New branch.
+ tree.addFieldPath("bar.baz");
+ assertEquals("bar.baz,foo", tree.toString());
+ // Redundant sub-path.
+ tree.addFieldPath("foo.bar");
+ assertEquals("bar.baz,foo", tree.toString());
+ // New branch from a non-root node.
+ tree.addFieldPath("bar.quz");
+ assertEquals("bar.baz,bar.quz,foo", tree.toString());
+ // A path that matches several existing sub-paths.
+ tree.addFieldPath("bar");
+ assertEquals("bar,foo", tree.toString());
+ }
+
+ public void testMergeFromFieldMask() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+ assertEquals("bar.baz,bar.quz,foo", tree.toString());
+ tree.mergeFromFieldMask(FieldMaskUtil.fromString("foo.bar,bar"));
+ assertEquals("bar,foo", tree.toString());
+ }
+
+ public void testIntersectFieldPath() throws Exception {
+ FieldMaskTree tree = new FieldMaskTree(FieldMaskUtil.fromString("foo,bar.baz,bar.quz"));
+ FieldMaskTree result = new FieldMaskTree();
+ // Empty path.
+ tree.intersectFieldPath("", result);
+ assertEquals("", result.toString());
+ // Non-exist path.
+ tree.intersectFieldPath("quz", result);
+ assertEquals("", result.toString());
+ // Sub-path of an existing leaf.
+ tree.intersectFieldPath("foo.bar", result);
+ assertEquals("foo.bar", result.toString());
+ // Match an existing leaf node.
+ tree.intersectFieldPath("foo", result);
+ assertEquals("foo", result.toString());
+ // Non-exist path.
+ tree.intersectFieldPath("bar.foo", result);
+ assertEquals("foo", result.toString());
+ // Match a non-leaf node.
+ tree.intersectFieldPath("bar", result);
+ assertEquals("bar.baz,bar.quz,foo", result.toString());
+ }
+
+ public void testMerge() throws Exception {
+ TestAllTypes value =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(1234)
+ .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678))
+ .addRepeatedInt32(4321)
+ .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765))
+ .build();
+ NestedTestAllTypes source =
+ NestedTestAllTypes.newBuilder()
+ .setPayload(value)
+ .setChild(NestedTestAllTypes.newBuilder().setPayload(value))
+ .build();
+ // Now we have a message source with the following structure:
+ // [root] -+- payload -+- optional_int32
+ // | +- optional_nested_message
+ // | +- repeated_int32
+ // | +- repeated_nested_message
+ // |
+ // +- child --- payload -+- optional_int32
+ // +- optional_nested_message
+ // +- repeated_int32
+ // +- repeated_nested_message
+
+ FieldMaskUtil.MergeOptions options = new FieldMaskUtil.MergeOptions();
+
+ // Test merging each individual field.
+ NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.optional_int32").merge(source, builder, options);
+ NestedTestAllTypes.Builder expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().setOptionalInt32(1234);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("payload.optional_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().addRepeatedInt32(4321);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("payload.repeated_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getPayloadBuilder().addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("child.payload.optional_int32")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().setOptionalInt32(1234);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("child.payload.optional_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected
+ .getChildBuilder()
+ .getPayloadBuilder()
+ .setOptionalNestedMessage(NestedMessage.newBuilder().setBb(5678));
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("child.payload.repeated_int32")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected.getChildBuilder().getPayloadBuilder().addRepeatedInt32(4321);
+ assertEquals(expected.build(), builder.build());
+
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("child.payload.repeated_nested_message")
+ .merge(source, builder, options);
+ expected = NestedTestAllTypes.newBuilder();
+ expected
+ .getChildBuilder()
+ .getPayloadBuilder()
+ .addRepeatedNestedMessage(NestedMessage.newBuilder().setBb(8765));
+ assertEquals(expected.build(), builder.build());
+
+ // Test merging all fields.
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree()
+ .addFieldPath("child")
+ .addFieldPath("payload")
+ .merge(source, builder, options);
+ assertEquals(source, builder.build());
+
+ // Test repeated options.
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().addRepeatedInt32(1000);
+ new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ // Default behavior is to append repeated fields.
+ assertEquals(2, builder.getPayload().getRepeatedInt32Count());
+ assertEquals(1000, builder.getPayload().getRepeatedInt32(0));
+ assertEquals(4321, builder.getPayload().getRepeatedInt32(1));
+ // Change to replace repeated fields.
+ options.setReplaceRepeatedFields(true);
+ new FieldMaskTree().addFieldPath("payload.repeated_int32").merge(source, builder, options);
+ assertEquals(1, builder.getPayload().getRepeatedInt32Count());
+ assertEquals(4321, builder.getPayload().getRepeatedInt32(0));
+
+ // Test message options.
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().setOptionalInt32(1000);
+ builder.getPayloadBuilder().setOptionalUint32(2000);
+ new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+ // Default behavior is to merge message fields.
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ assertEquals(2000, builder.getPayload().getOptionalUint32());
+
+ // Test merging unset message fields.
+ NestedTestAllTypes clearedSource = source.toBuilder().clearPayload().build();
+ builder = NestedTestAllTypes.newBuilder();
+ new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+ assertEquals(false, builder.hasPayload());
+
+ // Change to replace message fields.
+ options.setReplaceMessageFields(true);
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().setOptionalInt32(1000);
+ builder.getPayloadBuilder().setOptionalUint32(2000);
+ new FieldMaskTree().addFieldPath("payload").merge(source, builder, options);
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ assertEquals(0, builder.getPayload().getOptionalUint32());
+
+ // Test merging unset message fields.
+ builder = NestedTestAllTypes.newBuilder();
+ builder.getPayloadBuilder().setOptionalInt32(1000);
+ builder.getPayloadBuilder().setOptionalUint32(2000);
+ new FieldMaskTree().addFieldPath("payload").merge(clearedSource, builder, options);
+ assertEquals(false, builder.hasPayload());
+
+ // Test merging unset primitive fields.
+ builder = source.toBuilder();
+ builder.getPayloadBuilder().clearOptionalInt32();
+ NestedTestAllTypes sourceWithPayloadInt32Unset = builder.build();
+ builder = source.toBuilder();
+ new FieldMaskTree()
+ .addFieldPath("payload.optional_int32")
+ .merge(sourceWithPayloadInt32Unset, builder, options);
+ assertEquals(true, builder.getPayload().hasOptionalInt32());
+ assertEquals(0, builder.getPayload().getOptionalInt32());
+
+ // Change to clear unset primitive fields.
+ options.setReplacePrimitiveFields(true);
+ builder = source.toBuilder();
+ new FieldMaskTree()
+ .addFieldPath("payload.optional_int32")
+ .merge(sourceWithPayloadInt32Unset, builder, options);
+ assertEquals(true, builder.hasPayload());
+ assertEquals(false, builder.getPayload().hasOptionalInt32());
+ }
+}
diff --git a/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
new file mode 100644
index 0000000000..1a99857053
--- /dev/null
+++ b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/FieldMaskUtilTest.java
@@ -0,0 +1,213 @@
+// 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.util;
+
+import com.google.protobuf.FieldMask;
+import protobuf_unittest.UnittestProto.NestedTestAllTypes;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+
+import junit.framework.TestCase;
+
+/** Unit tests for {@link FieldMaskUtil}. */
+public class FieldMaskUtilTest extends TestCase {
+ public void testIsValid() throws Exception {
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload"));
+ assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "nonexist"));
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32"));
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_int32"));
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message"));
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message"));
+ assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.nonexist"));
+
+ assertTrue(
+ FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("payload")));
+ assertFalse(
+ FieldMaskUtil.isValid(NestedTestAllTypes.class, FieldMaskUtil.fromString("nonexist")));
+ assertFalse(
+ FieldMaskUtil.isValid(
+ NestedTestAllTypes.class, FieldMaskUtil.fromString("payload,nonexist")));
+
+ assertTrue(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "payload"));
+ assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.getDescriptor(), "nonexist"));
+
+ assertTrue(
+ FieldMaskUtil.isValid(
+ NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("payload")));
+ assertFalse(
+ FieldMaskUtil.isValid(
+ NestedTestAllTypes.getDescriptor(), FieldMaskUtil.fromString("nonexist")));
+
+ assertTrue(
+ FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_nested_message.bb"));
+ // Repeated fields cannot have sub-paths.
+ assertFalse(
+ FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.repeated_nested_message.bb"));
+ // Non-message fields cannot have sub-paths.
+ assertFalse(FieldMaskUtil.isValid(NestedTestAllTypes.class, "payload.optional_int32.bb"));
+ }
+
+ public void testToString() throws Exception {
+ assertEquals("", FieldMaskUtil.toString(FieldMask.getDefaultInstance()));
+ FieldMask mask = FieldMask.newBuilder().addPaths("foo").build();
+ assertEquals("foo", FieldMaskUtil.toString(mask));
+ mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar").build();
+ assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+
+ // Empty field paths are ignored.
+ mask =
+ FieldMask.newBuilder()
+ .addPaths("")
+ .addPaths("foo")
+ .addPaths("")
+ .addPaths("bar")
+ .addPaths("")
+ .build();
+ assertEquals("foo,bar", FieldMaskUtil.toString(mask));
+ }
+
+ public void testFromString() throws Exception {
+ FieldMask mask = FieldMaskUtil.fromString("");
+ assertEquals(0, mask.getPathsCount());
+ mask = FieldMaskUtil.fromString("foo");
+ assertEquals(1, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ mask = FieldMaskUtil.fromString("foo,bar.baz");
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ assertEquals("bar.baz", mask.getPaths(1));
+
+ // Empty field paths are ignore.
+ mask = FieldMaskUtil.fromString(",foo,,bar,");
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ assertEquals("bar", mask.getPaths(1));
+
+ // Check whether the field paths are valid if a class parameter is provided.
+ mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, ",payload");
+
+ try {
+ mask = FieldMaskUtil.fromString(NestedTestAllTypes.class, "payload,nonexist");
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testFromFieldNumbers() throws Exception {
+ FieldMask mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class);
+ assertEquals(0, mask.getPathsCount());
+ mask =
+ FieldMaskUtil.fromFieldNumbers(
+ TestAllTypes.class, TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER);
+ assertEquals(1, mask.getPathsCount());
+ assertEquals("optional_int32", mask.getPaths(0));
+ mask =
+ FieldMaskUtil.fromFieldNumbers(
+ TestAllTypes.class,
+ TestAllTypes.OPTIONAL_INT32_FIELD_NUMBER,
+ TestAllTypes.OPTIONAL_INT64_FIELD_NUMBER);
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("optional_int32", mask.getPaths(0));
+ assertEquals("optional_int64", mask.getPaths(1));
+
+ try {
+ int invalidFieldNumber = 1000;
+ mask = FieldMaskUtil.fromFieldNumbers(TestAllTypes.class, invalidFieldNumber);
+ fail("Exception is expected.");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testToJsonString() throws Exception {
+ FieldMask mask = FieldMask.getDefaultInstance();
+ assertEquals("", FieldMaskUtil.toJsonString(mask));
+ mask = FieldMask.newBuilder().addPaths("foo").build();
+ assertEquals("foo", FieldMaskUtil.toJsonString(mask));
+ mask = FieldMask.newBuilder().addPaths("foo.bar_baz").addPaths("").build();
+ assertEquals("foo.barBaz", FieldMaskUtil.toJsonString(mask));
+ mask = FieldMask.newBuilder().addPaths("foo").addPaths("bar_baz").build();
+ assertEquals("foo,barBaz", FieldMaskUtil.toJsonString(mask));
+ }
+
+ public void testFromJsonString() throws Exception {
+ FieldMask mask = FieldMaskUtil.fromJsonString("");
+ assertEquals(0, mask.getPathsCount());
+ mask = FieldMaskUtil.fromJsonString("foo");
+ assertEquals(1, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ mask = FieldMaskUtil.fromJsonString("foo.barBaz");
+ assertEquals(1, mask.getPathsCount());
+ assertEquals("foo.bar_baz", mask.getPaths(0));
+ mask = FieldMaskUtil.fromJsonString("foo,barBaz");
+ assertEquals(2, mask.getPathsCount());
+ assertEquals("foo", mask.getPaths(0));
+ assertEquals("bar_baz", mask.getPaths(1));
+ }
+
+ public void testUnion() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testAddFieldPath} to cover all scenarios.
+ FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+ FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+ FieldMask result = FieldMaskUtil.union(mask1, mask2);
+ assertEquals("bar,foo", FieldMaskUtil.toString(result));
+ }
+
+ public void testUnion_usingVarArgs() throws Exception {
+ FieldMask mask1 = FieldMaskUtil.fromString("foo");
+ FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar.quz");
+ FieldMask mask3 = FieldMaskUtil.fromString("bar.quz");
+ FieldMask mask4 = FieldMaskUtil.fromString("bar");
+ FieldMask result = FieldMaskUtil.union(mask1, mask2, mask3, mask4);
+ assertEquals("bar,foo", FieldMaskUtil.toString(result));
+ }
+
+ public void testIntersection() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testIntersectFieldPath} to cover all scenarios.
+ FieldMask mask1 = FieldMaskUtil.fromString("foo,bar.baz,bar.quz");
+ FieldMask mask2 = FieldMaskUtil.fromString("foo.bar,bar");
+ FieldMask result = FieldMaskUtil.intersection(mask1, mask2);
+ assertEquals("bar.baz,bar.quz,foo.bar", FieldMaskUtil.toString(result));
+ }
+
+ public void testMerge() throws Exception {
+ // Only test a simple case here and expect
+ // {@link FieldMaskTreeTest#testMerge} to cover all scenarios.
+ NestedTestAllTypes source =
+ NestedTestAllTypes.newBuilder()
+ .setPayload(TestAllTypes.newBuilder().setOptionalInt32(1234))
+ .build();
+ NestedTestAllTypes.Builder builder = NestedTestAllTypes.newBuilder();
+ FieldMaskUtil.merge(FieldMaskUtil.fromString("payload"), source, builder);
+ assertEquals(1234, builder.getPayload().getOptionalInt32());
+ }
+}
diff --git a/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
new file mode 100644
index 0000000000..de02c117e3
--- /dev/null
+++ b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -0,0 +1,1454 @@
+// 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.util;
+
+import com.google.protobuf.Any;
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ListValue;
+import com.google.protobuf.Message;
+import com.google.protobuf.NullValue;
+import com.google.protobuf.StringValue;
+import com.google.protobuf.Struct;
+import com.google.protobuf.UInt32Value;
+import com.google.protobuf.UInt64Value;
+import com.google.protobuf.Value;
+import com.google.protobuf.util.JsonFormat.TypeRegistry;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedEnum;
+import com.google.protobuf.util.JsonTestProto.TestAllTypes.NestedMessage;
+import com.google.protobuf.util.JsonTestProto.TestAny;
+import com.google.protobuf.util.JsonTestProto.TestCustomJsonName;
+import com.google.protobuf.util.JsonTestProto.TestDuration;
+import com.google.protobuf.util.JsonTestProto.TestFieldMask;
+import com.google.protobuf.util.JsonTestProto.TestMap;
+import com.google.protobuf.util.JsonTestProto.TestOneof;
+import com.google.protobuf.util.JsonTestProto.TestRecursive;
+import com.google.protobuf.util.JsonTestProto.TestStruct;
+import com.google.protobuf.util.JsonTestProto.TestTimestamp;
+import com.google.protobuf.util.JsonTestProto.TestWrappers;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import junit.framework.TestCase;
+
+public class JsonFormatTest extends TestCase {
+ public JsonFormatTest() {
+ // Test that locale does not affect JsonFormat.
+ Locale.setDefault(Locale.forLanguageTag("hi-IN"));
+ }
+
+ private void setAllFields(TestAllTypes.Builder builder) {
+ builder.setOptionalInt32(1234);
+ builder.setOptionalInt64(1234567890123456789L);
+ builder.setOptionalUint32(5678);
+ builder.setOptionalUint64(2345678901234567890L);
+ builder.setOptionalSint32(9012);
+ builder.setOptionalSint64(3456789012345678901L);
+ builder.setOptionalFixed32(3456);
+ builder.setOptionalFixed64(4567890123456789012L);
+ builder.setOptionalSfixed32(7890);
+ builder.setOptionalSfixed64(5678901234567890123L);
+ builder.setOptionalFloat(1.5f);
+ builder.setOptionalDouble(1.25);
+ builder.setOptionalBool(true);
+ builder.setOptionalString("Hello world!");
+ builder.setOptionalBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
+ builder.setOptionalNestedEnum(NestedEnum.BAR);
+ builder.getOptionalNestedMessageBuilder().setValue(100);
+
+ builder.addRepeatedInt32(1234);
+ builder.addRepeatedInt64(1234567890123456789L);
+ builder.addRepeatedUint32(5678);
+ builder.addRepeatedUint64(2345678901234567890L);
+ builder.addRepeatedSint32(9012);
+ builder.addRepeatedSint64(3456789012345678901L);
+ builder.addRepeatedFixed32(3456);
+ builder.addRepeatedFixed64(4567890123456789012L);
+ builder.addRepeatedSfixed32(7890);
+ builder.addRepeatedSfixed64(5678901234567890123L);
+ builder.addRepeatedFloat(1.5f);
+ builder.addRepeatedDouble(1.25);
+ builder.addRepeatedBool(true);
+ builder.addRepeatedString("Hello world!");
+ builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {0, 1, 2}));
+ builder.addRepeatedNestedEnum(NestedEnum.BAR);
+ builder.addRepeatedNestedMessageBuilder().setValue(100);
+
+ builder.addRepeatedInt32(234);
+ builder.addRepeatedInt64(234567890123456789L);
+ builder.addRepeatedUint32(678);
+ builder.addRepeatedUint64(345678901234567890L);
+ builder.addRepeatedSint32(012);
+ builder.addRepeatedSint64(456789012345678901L);
+ builder.addRepeatedFixed32(456);
+ builder.addRepeatedFixed64(567890123456789012L);
+ builder.addRepeatedSfixed32(890);
+ builder.addRepeatedSfixed64(678901234567890123L);
+ builder.addRepeatedFloat(11.5f);
+ builder.addRepeatedDouble(11.25);
+ builder.addRepeatedBool(true);
+ builder.addRepeatedString("ello world!");
+ builder.addRepeatedBytes(ByteString.copyFrom(new byte[] {1, 2}));
+ builder.addRepeatedNestedEnum(NestedEnum.BAZ);
+ builder.addRepeatedNestedMessageBuilder().setValue(200);
+ }
+
+ private void assertRoundTripEquals(Message message) throws Exception {
+ assertRoundTripEquals(message, TypeRegistry.getEmptyTypeRegistry());
+ }
+
+ private void assertRoundTripEquals(Message message, TypeRegistry registry) throws Exception {
+ JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+ JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
+ Message.Builder builder = message.newBuilderForType();
+ parser.merge(printer.print(message), builder);
+ Message parsedMessage = builder.build();
+ assertEquals(message.toString(), parsedMessage.toString());
+ }
+
+ private String toJsonString(Message message) throws IOException {
+ return JsonFormat.printer().print(message);
+ }
+ private String toCompactJsonString(Message message) throws IOException {
+ return JsonFormat.printer().omittingInsignificantWhitespace().print(message);
+ }
+
+ private void mergeFromJson(String json, Message.Builder builder) throws IOException {
+ JsonFormat.parser().merge(json, builder);
+ }
+
+ public void testAllFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ TestAllTypes message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"optionalInt32\": 1234,\n"
+ + " \"optionalInt64\": \"1234567890123456789\",\n"
+ + " \"optionalUint32\": 5678,\n"
+ + " \"optionalUint64\": \"2345678901234567890\",\n"
+ + " \"optionalSint32\": 9012,\n"
+ + " \"optionalSint64\": \"3456789012345678901\",\n"
+ + " \"optionalFixed32\": 3456,\n"
+ + " \"optionalFixed64\": \"4567890123456789012\",\n"
+ + " \"optionalSfixed32\": 7890,\n"
+ + " \"optionalSfixed64\": \"5678901234567890123\",\n"
+ + " \"optionalFloat\": 1.5,\n"
+ + " \"optionalDouble\": 1.25,\n"
+ + " \"optionalBool\": true,\n"
+ + " \"optionalString\": \"Hello world!\",\n"
+ + " \"optionalBytes\": \"AAEC\",\n"
+ + " \"optionalNestedMessage\": {\n"
+ + " \"value\": 100\n"
+ + " },\n"
+ + " \"optionalNestedEnum\": \"BAR\",\n"
+ + " \"repeatedInt32\": [1234, 234],\n"
+ + " \"repeatedInt64\": [\"1234567890123456789\", \"234567890123456789\"],\n"
+ + " \"repeatedUint32\": [5678, 678],\n"
+ + " \"repeatedUint64\": [\"2345678901234567890\", \"345678901234567890\"],\n"
+ + " \"repeatedSint32\": [9012, 10],\n"
+ + " \"repeatedSint64\": [\"3456789012345678901\", \"456789012345678901\"],\n"
+ + " \"repeatedFixed32\": [3456, 456],\n"
+ + " \"repeatedFixed64\": [\"4567890123456789012\", \"567890123456789012\"],\n"
+ + " \"repeatedSfixed32\": [7890, 890],\n"
+ + " \"repeatedSfixed64\": [\"5678901234567890123\", \"678901234567890123\"],\n"
+ + " \"repeatedFloat\": [1.5, 11.5],\n"
+ + " \"repeatedDouble\": [1.25, 11.25],\n"
+ + " \"repeatedBool\": [true, true],\n"
+ + " \"repeatedString\": [\"Hello world!\", \"ello world!\"],\n"
+ + " \"repeatedBytes\": [\"AAEC\", \"AQI=\"],\n"
+ + " \"repeatedNestedMessage\": [{\n"
+ + " \"value\": 100\n"
+ + " }, {\n"
+ + " \"value\": 200\n"
+ + " }],\n"
+ + " \"repeatedNestedEnum\": [\"BAR\", \"BAZ\"]\n"
+ + "}",
+ toJsonString(message));
+
+ assertRoundTripEquals(message);
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .setOptionalNestedEnumValue(12345)
+ .addRepeatedNestedEnumValue(12345)
+ .addRepeatedNestedEnumValue(0)
+ .build();
+ assertEquals(
+ "{\n"
+ + " \"optionalNestedEnum\": 12345,\n"
+ + " \"repeatedNestedEnum\": [12345, \"FOO\"]\n"
+ + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+
+ TestMap.Builder mapBuilder = TestMap.newBuilder();
+ mapBuilder.putInt32ToEnumMapValue(1, 0);
+ Map<Integer, Integer> mapWithInvalidValues = new HashMap<Integer, Integer>();
+ mapWithInvalidValues.put(2, 12345);
+ mapBuilder.putAllInt32ToEnumMapValue(mapWithInvalidValues);
+ TestMap mapMessage = mapBuilder.build();
+ assertEquals(
+ "{\n"
+ + " \"int32ToEnumMap\": {\n"
+ + " \"1\": \"FOO\",\n"
+ + " \"2\": 12345\n"
+ + " }\n"
+ + "}",
+ toJsonString(mapMessage));
+ assertRoundTripEquals(mapMessage);
+ }
+
+ public void testSpecialFloatValues() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .addRepeatedFloat(Float.NaN)
+ .addRepeatedFloat(Float.POSITIVE_INFINITY)
+ .addRepeatedFloat(Float.NEGATIVE_INFINITY)
+ .addRepeatedDouble(Double.NaN)
+ .addRepeatedDouble(Double.POSITIVE_INFINITY)
+ .addRepeatedDouble(Double.NEGATIVE_INFINITY)
+ .build();
+ assertEquals(
+ "{\n"
+ + " \"repeatedFloat\": [\"NaN\", \"Infinity\", \"-Infinity\"],\n"
+ + " \"repeatedDouble\": [\"NaN\", \"Infinity\", \"-Infinity\"]\n"
+ + "}",
+ toJsonString(message));
+
+ assertRoundTripEquals(message);
+ }
+
+ public void testParserAcceptStringForNumbericField() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": \"1234\",\n"
+ + " \"optionalUint32\": \"5678\",\n"
+ + " \"optionalSint32\": \"9012\",\n"
+ + " \"optionalFixed32\": \"3456\",\n"
+ + " \"optionalSfixed32\": \"7890\",\n"
+ + " \"optionalFloat\": \"1.5\",\n"
+ + " \"optionalDouble\": \"1.25\",\n"
+ + " \"optionalBool\": \"true\"\n"
+ + "}",
+ builder);
+ TestAllTypes message = builder.build();
+ assertEquals(1234, message.getOptionalInt32());
+ assertEquals(5678, message.getOptionalUint32());
+ assertEquals(9012, message.getOptionalSint32());
+ assertEquals(3456, message.getOptionalFixed32());
+ assertEquals(7890, message.getOptionalSfixed32());
+ assertEquals(1.5f, message.getOptionalFloat());
+ assertEquals(1.25, message.getOptionalDouble());
+ assertEquals(true, message.getOptionalBool());
+ }
+
+ public void testParserAcceptFloatingPointValueForIntegerField() throws Exception {
+ // Test that numeric values like "1.000", "1e5" will also be accepted.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"repeatedInt32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+ + " \"repeatedUint32\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+ + " \"repeatedInt64\": [1.000, 1e5, \"1.000\", \"1e5\"],\n"
+ + " \"repeatedUint64\": [1.000, 1e5, \"1.000\", \"1e5\"]\n"
+ + "}",
+ builder);
+ int[] expectedValues = new int[] {1, 100000, 1, 100000};
+ assertEquals(4, builder.getRepeatedInt32Count());
+ assertEquals(4, builder.getRepeatedUint32Count());
+ assertEquals(4, builder.getRepeatedInt64Count());
+ assertEquals(4, builder.getRepeatedUint64Count());
+ for (int i = 0; i < 4; ++i) {
+ assertEquals(expectedValues[i], builder.getRepeatedInt32(i));
+ assertEquals(expectedValues[i], builder.getRepeatedUint32(i));
+ assertEquals(expectedValues[i], builder.getRepeatedInt64(i));
+ assertEquals(expectedValues[i], builder.getRepeatedUint64(i));
+ }
+
+ // Non-integers will still be rejected.
+ assertRejects("optionalInt32", "1.5");
+ assertRejects("optionalUint32", "1.5");
+ assertRejects("optionalInt64", "1.5");
+ assertRejects("optionalUint64", "1.5");
+ }
+
+ private void assertRejects(String name, String value) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ // Numeric form is rejected.
+ mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ try {
+ // String form is also rejected.
+ mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ private void assertAccepts(String name, String value) throws IOException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // Both numeric form and string form are accepted.
+ mergeFromJson("{\"" + name + "\":" + value + "}", builder);
+ builder.clear();
+ mergeFromJson("{\"" + name + "\":\"" + value + "\"}", builder);
+ }
+
+ public void testParserRejectOutOfRangeNumericValues() throws Exception {
+ assertAccepts("optionalInt32", String.valueOf(Integer.MAX_VALUE));
+ assertAccepts("optionalInt32", String.valueOf(Integer.MIN_VALUE));
+ assertRejects("optionalInt32", String.valueOf(Integer.MAX_VALUE + 1L));
+ assertRejects("optionalInt32", String.valueOf(Integer.MIN_VALUE - 1L));
+
+ assertAccepts("optionalUint32", String.valueOf(Integer.MAX_VALUE + 1L));
+ assertRejects("optionalUint32", "123456789012345");
+ assertRejects("optionalUint32", "-1");
+
+ BigInteger one = new BigInteger("1");
+ BigInteger maxLong = new BigInteger(String.valueOf(Long.MAX_VALUE));
+ BigInteger minLong = new BigInteger(String.valueOf(Long.MIN_VALUE));
+ assertAccepts("optionalInt64", maxLong.toString());
+ assertAccepts("optionalInt64", minLong.toString());
+ assertRejects("optionalInt64", maxLong.add(one).toString());
+ assertRejects("optionalInt64", minLong.subtract(one).toString());
+
+ assertAccepts("optionalUint64", maxLong.add(one).toString());
+ assertRejects("optionalUint64", "1234567890123456789012345");
+ assertRejects("optionalUint64", "-1");
+
+ assertAccepts("optionalBool", "true");
+ assertRejects("optionalBool", "1");
+ assertRejects("optionalBool", "0");
+
+ assertAccepts("optionalFloat", String.valueOf(Float.MAX_VALUE));
+ assertAccepts("optionalFloat", String.valueOf(-Float.MAX_VALUE));
+ assertRejects("optionalFloat", String.valueOf(Double.MAX_VALUE));
+ assertRejects("optionalFloat", String.valueOf(-Double.MAX_VALUE));
+
+ BigDecimal moreThanOne = new BigDecimal("1.000001");
+ BigDecimal maxDouble = new BigDecimal(Double.MAX_VALUE);
+ BigDecimal minDouble = new BigDecimal(-Double.MAX_VALUE);
+ assertAccepts("optionalDouble", maxDouble.toString());
+ assertAccepts("optionalDouble", minDouble.toString());
+ assertRejects("optionalDouble", maxDouble.multiply(moreThanOne).toString());
+ assertRejects("optionalDouble", minDouble.multiply(moreThanOne).toString());
+ }
+
+ public void testParserAcceptNull() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalInt32\": null,\n"
+ + " \"optionalInt64\": null,\n"
+ + " \"optionalUint32\": null,\n"
+ + " \"optionalUint64\": null,\n"
+ + " \"optionalSint32\": null,\n"
+ + " \"optionalSint64\": null,\n"
+ + " \"optionalFixed32\": null,\n"
+ + " \"optionalFixed64\": null,\n"
+ + " \"optionalSfixed32\": null,\n"
+ + " \"optionalSfixed64\": null,\n"
+ + " \"optionalFloat\": null,\n"
+ + " \"optionalDouble\": null,\n"
+ + " \"optionalBool\": null,\n"
+ + " \"optionalString\": null,\n"
+ + " \"optionalBytes\": null,\n"
+ + " \"optionalNestedMessage\": null,\n"
+ + " \"optionalNestedEnum\": null,\n"
+ + " \"repeatedInt32\": null,\n"
+ + " \"repeatedInt64\": null,\n"
+ + " \"repeatedUint32\": null,\n"
+ + " \"repeatedUint64\": null,\n"
+ + " \"repeatedSint32\": null,\n"
+ + " \"repeatedSint64\": null,\n"
+ + " \"repeatedFixed32\": null,\n"
+ + " \"repeatedFixed64\": null,\n"
+ + " \"repeatedSfixed32\": null,\n"
+ + " \"repeatedSfixed64\": null,\n"
+ + " \"repeatedFloat\": null,\n"
+ + " \"repeatedDouble\": null,\n"
+ + " \"repeatedBool\": null,\n"
+ + " \"repeatedString\": null,\n"
+ + " \"repeatedBytes\": null,\n"
+ + " \"repeatedNestedMessage\": null,\n"
+ + " \"repeatedNestedEnum\": null\n"
+ + "}",
+ builder);
+ TestAllTypes message = builder.build();
+ assertEquals(TestAllTypes.getDefaultInstance(), message);
+
+ // Repeated field elements cannot be null.
+ try {
+ builder = TestAllTypes.newBuilder();
+ mergeFromJson("{\n" + " \"repeatedInt32\": [null, null],\n" + "}", builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+
+ try {
+ builder = TestAllTypes.newBuilder();
+ mergeFromJson("{\n" + " \"repeatedNestedMessage\": [null, null],\n" + "}", builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+ }
+
+ public void testNullInOneof() throws Exception {
+ TestOneof.Builder builder = TestOneof.newBuilder();
+ mergeFromJson("{\n" + " \"oneofNullValue\": null \n" + "}", builder);
+ TestOneof message = builder.build();
+ assertEquals(TestOneof.OneofFieldCase.ONEOF_NULL_VALUE, message.getOneofFieldCase());
+ assertEquals(NullValue.NULL_VALUE, message.getOneofNullValue());
+ }
+
+ public void testParserRejectDuplicatedFields() throws Exception {
+ // TODO(xiaofeng): The parser we are currently using (GSON) will accept and keep the last
+ // one if multiple entries have the same name. This is not the desired behavior but it can
+ // only be fixed by using our own parser. Here we only test the cases where the names are
+ // different but still referring to the same field.
+
+ // Duplicated optional fields.
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"optionalNestedMessage\": {},\n"
+ + " \"optional_nested_message\": {}\n"
+ + "}",
+ builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+
+ // Duplicated repeated fields.
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"repeatedNestedMessage\": [null, null],\n"
+ + " \"repeated_nested_message\": [null, null]\n"
+ + "}",
+ builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+
+ // Duplicated oneof fields.
+ try {
+ TestOneof.Builder builder = TestOneof.newBuilder();
+ mergeFromJson("{\n" + " \"oneofInt32\": 1,\n" + " \"oneof_int32\": 2\n" + "}", builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+ }
+
+ public void testMapFields() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ builder.putInt32ToInt32Map(1, 10);
+ builder.putInt64ToInt32Map(1234567890123456789L, 10);
+ builder.putUint32ToInt32Map(2, 20);
+ builder.putUint64ToInt32Map(2234567890123456789L, 20);
+ builder.putSint32ToInt32Map(3, 30);
+ builder.putSint64ToInt32Map(3234567890123456789L, 30);
+ builder.putFixed32ToInt32Map(4, 40);
+ builder.putFixed64ToInt32Map(4234567890123456789L, 40);
+ builder.putSfixed32ToInt32Map(5, 50);
+ builder.putSfixed64ToInt32Map(5234567890123456789L, 50);
+ builder.putBoolToInt32Map(false, 6);
+ builder.putStringToInt32Map("Hello", 10);
+
+ builder.putInt32ToInt64Map(1, 1234567890123456789L);
+ builder.putInt32ToUint32Map(2, 20);
+ builder.putInt32ToUint64Map(2, 2234567890123456789L);
+ builder.putInt32ToSint32Map(3, 30);
+ builder.putInt32ToSint64Map(3, 3234567890123456789L);
+ builder.putInt32ToFixed32Map(4, 40);
+ builder.putInt32ToFixed64Map(4, 4234567890123456789L);
+ builder.putInt32ToSfixed32Map(5, 50);
+ builder.putInt32ToSfixed64Map(5, 5234567890123456789L);
+ builder.putInt32ToFloatMap(6, 1.5f);
+ builder.putInt32ToDoubleMap(6, 1.25);
+ builder.putInt32ToBoolMap(7, false);
+ builder.putInt32ToStringMap(7, "World");
+ builder.putInt32ToBytesMap(8, ByteString.copyFrom(new byte[] {1, 2, 3}));
+ builder.putInt32ToMessageMap(8, NestedMessage.newBuilder().setValue(1234).build());
+ builder.putInt32ToEnumMap(9, NestedEnum.BAR);
+ TestMap message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32ToInt32Map\": {\n"
+ + " \"1\": 10\n"
+ + " },\n"
+ + " \"int64ToInt32Map\": {\n"
+ + " \"1234567890123456789\": 10\n"
+ + " },\n"
+ + " \"uint32ToInt32Map\": {\n"
+ + " \"2\": 20\n"
+ + " },\n"
+ + " \"uint64ToInt32Map\": {\n"
+ + " \"2234567890123456789\": 20\n"
+ + " },\n"
+ + " \"sint32ToInt32Map\": {\n"
+ + " \"3\": 30\n"
+ + " },\n"
+ + " \"sint64ToInt32Map\": {\n"
+ + " \"3234567890123456789\": 30\n"
+ + " },\n"
+ + " \"fixed32ToInt32Map\": {\n"
+ + " \"4\": 40\n"
+ + " },\n"
+ + " \"fixed64ToInt32Map\": {\n"
+ + " \"4234567890123456789\": 40\n"
+ + " },\n"
+ + " \"sfixed32ToInt32Map\": {\n"
+ + " \"5\": 50\n"
+ + " },\n"
+ + " \"sfixed64ToInt32Map\": {\n"
+ + " \"5234567890123456789\": 50\n"
+ + " },\n"
+ + " \"boolToInt32Map\": {\n"
+ + " \"false\": 6\n"
+ + " },\n"
+ + " \"stringToInt32Map\": {\n"
+ + " \"Hello\": 10\n"
+ + " },\n"
+ + " \"int32ToInt64Map\": {\n"
+ + " \"1\": \"1234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToUint32Map\": {\n"
+ + " \"2\": 20\n"
+ + " },\n"
+ + " \"int32ToUint64Map\": {\n"
+ + " \"2\": \"2234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToSint32Map\": {\n"
+ + " \"3\": 30\n"
+ + " },\n"
+ + " \"int32ToSint64Map\": {\n"
+ + " \"3\": \"3234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToFixed32Map\": {\n"
+ + " \"4\": 40\n"
+ + " },\n"
+ + " \"int32ToFixed64Map\": {\n"
+ + " \"4\": \"4234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToSfixed32Map\": {\n"
+ + " \"5\": 50\n"
+ + " },\n"
+ + " \"int32ToSfixed64Map\": {\n"
+ + " \"5\": \"5234567890123456789\"\n"
+ + " },\n"
+ + " \"int32ToFloatMap\": {\n"
+ + " \"6\": 1.5\n"
+ + " },\n"
+ + " \"int32ToDoubleMap\": {\n"
+ + " \"6\": 1.25\n"
+ + " },\n"
+ + " \"int32ToBoolMap\": {\n"
+ + " \"7\": false\n"
+ + " },\n"
+ + " \"int32ToStringMap\": {\n"
+ + " \"7\": \"World\"\n"
+ + " },\n"
+ + " \"int32ToBytesMap\": {\n"
+ + " \"8\": \"AQID\"\n"
+ + " },\n"
+ + " \"int32ToMessageMap\": {\n"
+ + " \"8\": {\n"
+ + " \"value\": 1234\n"
+ + " }\n"
+ + " },\n"
+ + " \"int32ToEnumMap\": {\n"
+ + " \"9\": \"BAR\"\n"
+ + " }\n"
+ + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+
+ // Test multiple entries.
+ builder = TestMap.newBuilder();
+ builder.putInt32ToInt32Map(1, 2);
+ builder.putInt32ToInt32Map(3, 4);
+ message = builder.build();
+
+ assertEquals(
+ "{\n" + " \"int32ToInt32Map\": {\n" + " \"1\": 2,\n" + " \"3\": 4\n" + " }\n" + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testMapNullValueIsRejected() throws Exception {
+ try {
+ TestMap.Builder builder = TestMap.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"int32ToInt32Map\": {null: 1},\n"
+ + " \"int32ToMessageMap\": {null: 2}\n"
+ + "}",
+ builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+
+ try {
+ TestMap.Builder builder = TestMap.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"int32ToInt32Map\": {\"1\": null},\n"
+ + " \"int32ToMessageMap\": {\"2\": null}\n"
+ + "}",
+ builder);
+ fail();
+ } catch (InvalidProtocolBufferException e) {
+ // Exception expected.
+ }
+ }
+
+ public void testParserAcceptNonQuotedObjectKey() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ mergeFromJson(
+ "{\n" + " int32ToInt32Map: {1: 2},\n" + " stringToInt32Map: {hello: 3}\n" + "}", builder);
+ TestMap message = builder.build();
+ assertEquals(2, message.getInt32ToInt32Map().get(1).intValue());
+ assertEquals(3, message.getStringToInt32Map().get("hello").intValue());
+ }
+
+ public void testWrappers() throws Exception {
+ TestWrappers.Builder builder = TestWrappers.newBuilder();
+ builder.getBoolValueBuilder().setValue(false);
+ builder.getInt32ValueBuilder().setValue(0);
+ builder.getInt64ValueBuilder().setValue(0);
+ builder.getUint32ValueBuilder().setValue(0);
+ builder.getUint64ValueBuilder().setValue(0);
+ builder.getFloatValueBuilder().setValue(0.0f);
+ builder.getDoubleValueBuilder().setValue(0.0);
+ builder.getStringValueBuilder().setValue("");
+ builder.getBytesValueBuilder().setValue(ByteString.EMPTY);
+ TestWrappers message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32Value\": 0,\n"
+ + " \"uint32Value\": 0,\n"
+ + " \"int64Value\": \"0\",\n"
+ + " \"uint64Value\": \"0\",\n"
+ + " \"floatValue\": 0.0,\n"
+ + " \"doubleValue\": 0.0,\n"
+ + " \"boolValue\": false,\n"
+ + " \"stringValue\": \"\",\n"
+ + " \"bytesValue\": \"\"\n"
+ + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+
+ builder = TestWrappers.newBuilder();
+ builder.getBoolValueBuilder().setValue(true);
+ builder.getInt32ValueBuilder().setValue(1);
+ builder.getInt64ValueBuilder().setValue(2);
+ builder.getUint32ValueBuilder().setValue(3);
+ builder.getUint64ValueBuilder().setValue(4);
+ builder.getFloatValueBuilder().setValue(5.0f);
+ builder.getDoubleValueBuilder().setValue(6.0);
+ builder.getStringValueBuilder().setValue("7");
+ builder.getBytesValueBuilder().setValue(ByteString.copyFrom(new byte[] {8}));
+ message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"int32Value\": 1,\n"
+ + " \"uint32Value\": 3,\n"
+ + " \"int64Value\": \"2\",\n"
+ + " \"uint64Value\": \"4\",\n"
+ + " \"floatValue\": 5.0,\n"
+ + " \"doubleValue\": 6.0,\n"
+ + " \"boolValue\": true,\n"
+ + " \"stringValue\": \"7\",\n"
+ + " \"bytesValue\": \"CA==\"\n"
+ + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testTimestamp() throws Exception {
+ TestTimestamp message =
+ TestTimestamp.newBuilder()
+ .setTimestampValue(Timestamps.parse("1970-01-01T00:00:00Z"))
+ .build();
+
+ assertEquals(
+ "{\n" + " \"timestampValue\": \"1970-01-01T00:00:00Z\"\n" + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testDuration() throws Exception {
+ TestDuration message =
+ TestDuration.newBuilder().setDurationValue(Durations.parse("12345s")).build();
+
+ assertEquals("{\n" + " \"durationValue\": \"12345s\"\n" + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testFieldMask() throws Exception {
+ TestFieldMask message =
+ TestFieldMask.newBuilder()
+ .setFieldMaskValue(FieldMaskUtil.fromString("foo.bar,baz,foo_bar.baz"))
+ .build();
+
+ assertEquals(
+ "{\n" + " \"fieldMaskValue\": \"foo.bar,baz,fooBar.baz\"\n" + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testStruct() throws Exception {
+ // Build a struct with all possible values.
+ TestStruct.Builder builder = TestStruct.newBuilder();
+ Struct.Builder structBuilder = builder.getStructValueBuilder();
+ structBuilder.putFields("null_value", Value.newBuilder().setNullValueValue(0).build());
+ structBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1.25).build());
+ structBuilder.putFields("string_value", Value.newBuilder().setStringValue("hello").build());
+ Struct.Builder subStructBuilder = Struct.newBuilder();
+ subStructBuilder.putFields("number_value", Value.newBuilder().setNumberValue(1234).build());
+ structBuilder.putFields(
+ "struct_value", Value.newBuilder().setStructValue(subStructBuilder.build()).build());
+ ListValue.Builder listBuilder = ListValue.newBuilder();
+ listBuilder.addValues(Value.newBuilder().setNumberValue(1.125).build());
+ listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
+ structBuilder.putFields(
+ "list_value", Value.newBuilder().setListValue(listBuilder.build()).build());
+ TestStruct message = builder.build();
+
+ assertEquals(
+ "{\n"
+ + " \"structValue\": {\n"
+ + " \"null_value\": null,\n"
+ + " \"number_value\": 1.25,\n"
+ + " \"string_value\": \"hello\",\n"
+ + " \"struct_value\": {\n"
+ + " \"number_value\": 1234.0\n"
+ + " },\n"
+ + " \"list_value\": [1.125, null]\n"
+ + " }\n"
+ + "}",
+ toJsonString(message));
+ assertRoundTripEquals(message);
+
+ builder = TestStruct.newBuilder();
+ builder.setValue(Value.newBuilder().setNullValueValue(0).build());
+ message = builder.build();
+ assertEquals("{\n" + " \"value\": null\n" + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+
+ builder = TestStruct.newBuilder();
+ listBuilder = builder.getListValueBuilder();
+ listBuilder.addValues(Value.newBuilder().setNumberValue(31831.125).build());
+ listBuilder.addValues(Value.newBuilder().setNullValueValue(0).build());
+ message = builder.build();
+ assertEquals("{\n" + " \"listValue\": [31831.125, null]\n" + "}", toJsonString(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testAnyFields() throws Exception {
+ TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
+ TestAny message = TestAny.newBuilder().setAnyValue(Any.pack(content)).build();
+
+ // A TypeRegistry must be provided in order to convert Any types.
+ try {
+ toJsonString(message);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+
+ JsonFormat.TypeRegistry registry =
+ JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
+ JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+
+ assertEquals(
+ "{\n"
+ + " \"anyValue\": {\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 1234\n"
+ + " }\n"
+ + "}",
+ printer.print(message));
+ assertRoundTripEquals(message, registry);
+
+ TestAny messageWithDefaultAnyValue =
+ TestAny.newBuilder().setAnyValue(Any.getDefaultInstance()).build();
+ assertEquals(
+ "{\n"
+ + " \"anyValue\": {}\n"
+ + "}",
+ printer.print(messageWithDefaultAnyValue));
+ assertRoundTripEquals(messageWithDefaultAnyValue, registry);
+
+ // Well-known types have a special formatting when embedded in Any.
+ //
+ // 1. Any in Any.
+ Any anyMessage = Any.pack(Any.pack(content));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+ + " \"value\": {\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 1234\n"
+ + " }\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 2. Wrappers in Any.
+ anyMessage = Any.pack(Int32Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
+ + " \"value\": 12345\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(UInt32Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.UInt32Value\",\n"
+ + " \"value\": 12345\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(Int64Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
+ + " \"value\": \"12345\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(UInt64Value.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.UInt64Value\",\n"
+ + " \"value\": \"12345\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(FloatValue.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.FloatValue\",\n"
+ + " \"value\": 12345.0\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(DoubleValue.newBuilder().setValue(12345).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.DoubleValue\",\n"
+ + " \"value\": 12345.0\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(BoolValue.newBuilder().setValue(true).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
+ + " \"value\": true\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage = Any.pack(StringValue.newBuilder().setValue("Hello").build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.StringValue\",\n"
+ + " \"value\": \"Hello\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ anyMessage =
+ Any.pack(BytesValue.newBuilder().setValue(ByteString.copyFrom(new byte[] {1, 2})).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BytesValue\",\n"
+ + " \"value\": \"AQI=\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 3. Timestamp in Any.
+ anyMessage = Any.pack(Timestamps.parse("1969-12-31T23:59:59Z"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
+ + " \"value\": \"1969-12-31T23:59:59Z\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 4. Duration in Any
+ anyMessage = Any.pack(Durations.parse("12345.10s"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
+ + " \"value\": \"12345.100s\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 5. FieldMask in Any
+ anyMessage = Any.pack(FieldMaskUtil.fromString("foo.bar,baz"));
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
+ + " \"value\": \"foo.bar,baz\"\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 6. Struct in Any
+ Struct.Builder structBuilder = Struct.newBuilder();
+ structBuilder.putFields("number", Value.newBuilder().setNumberValue(1.125).build());
+ anyMessage = Any.pack(structBuilder.build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
+ + " \"value\": {\n"
+ + " \"number\": 1.125\n"
+ + " }\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 7. Value (number type) in Any
+ Value.Builder valueBuilder = Value.newBuilder();
+ valueBuilder.setNumberValue(1);
+ anyMessage = Any.pack(valueBuilder.build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
+ + " \"value\": 1.0\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+
+ // 8. Value (null type) in Any
+ anyMessage = Any.pack(Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build());
+ assertEquals(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
+ + " \"value\": null\n"
+ + "}",
+ printer.print(anyMessage));
+ assertRoundTripEquals(anyMessage, registry);
+ }
+
+ public void testAnyInMaps() throws Exception {
+ JsonFormat.TypeRegistry registry =
+ JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
+ JsonFormat.Printer printer = JsonFormat.printer().usingTypeRegistry(registry);
+
+ TestAny.Builder testAny = TestAny.newBuilder();
+ testAny.putAnyMap("int32_wrapper", Any.pack(Int32Value.newBuilder().setValue(123).build()));
+ testAny.putAnyMap("int64_wrapper", Any.pack(Int64Value.newBuilder().setValue(456).build()));
+ testAny.putAnyMap("timestamp", Any.pack(Timestamps.parse("1969-12-31T23:59:59Z")));
+ testAny.putAnyMap("duration", Any.pack(Durations.parse("12345.1s")));
+ testAny.putAnyMap("field_mask", Any.pack(FieldMaskUtil.fromString("foo.bar,baz")));
+ Value numberValue = Value.newBuilder().setNumberValue(1.125).build();
+ Struct.Builder struct = Struct.newBuilder();
+ struct.putFields("number", numberValue);
+ testAny.putAnyMap("struct", Any.pack(struct.build()));
+ Value nullValue = Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build();
+ testAny.putAnyMap(
+ "list_value",
+ Any.pack(ListValue.newBuilder().addValues(numberValue).addValues(nullValue).build()));
+ testAny.putAnyMap("number_value", Any.pack(numberValue));
+ testAny.putAnyMap("any_value_number", Any.pack(Any.pack(numberValue)));
+ testAny.putAnyMap("any_value_default", Any.pack(Any.getDefaultInstance()));
+ testAny.putAnyMap("default", Any.getDefaultInstance());
+
+ assertEquals(
+ "{\n"
+ + " \"anyMap\": {\n"
+ + " \"int32_wrapper\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int32Value\",\n"
+ + " \"value\": 123\n"
+ + " },\n"
+ + " \"int64_wrapper\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Int64Value\",\n"
+ + " \"value\": \"456\"\n"
+ + " },\n"
+ + " \"timestamp\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Timestamp\",\n"
+ + " \"value\": \"1969-12-31T23:59:59Z\"\n"
+ + " },\n"
+ + " \"duration\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n"
+ + " \"value\": \"12345.100s\"\n"
+ + " },\n"
+ + " \"field_mask\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.FieldMask\",\n"
+ + " \"value\": \"foo.bar,baz\"\n"
+ + " },\n"
+ + " \"struct\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Struct\",\n"
+ + " \"value\": {\n"
+ + " \"number\": 1.125\n"
+ + " }\n"
+ + " },\n"
+ + " \"list_value\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.ListValue\",\n"
+ + " \"value\": [1.125, null]\n"
+ + " },\n"
+ + " \"number_value\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
+ + " \"value\": 1.125\n"
+ + " },\n"
+ + " \"any_value_number\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+ + " \"value\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Value\",\n"
+ + " \"value\": 1.125\n"
+ + " }\n"
+ + " },\n"
+ + " \"any_value_default\": {\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.Any\",\n"
+ + " \"value\": {}\n"
+ + " },\n"
+ + " \"default\": {}\n"
+ + " }\n"
+ + "}",
+ printer.print(testAny.build()));
+ assertRoundTripEquals(testAny.build(), registry);
+ }
+
+ public void testParserMissingTypeUrl() throws Exception {
+ try {
+ Any.Builder builder = Any.newBuilder();
+ mergeFromJson("{\n" + " \"optionalInt32\": 1234\n" + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserUnexpectedTypeUrl() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/json_test.TestAllTypes\",\n"
+ + " \"optionalInt32\": 12345\n"
+ + "}",
+ builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserRejectTrailingComma() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson("{\n" + " \"optionalInt32\": 12345,\n" + "}", builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ // Expected.
+ }
+
+ // TODO(xiaofeng): GSON allows trailing comma in arrays even after I set
+ // the JsonReader to non-lenient mode. If we want to enforce strict JSON
+ // compliance, we might want to switch to a different JSON parser or
+ // implement one by ourselves.
+ // try {
+ // TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ // JsonFormat.merge(
+ // "{\n"
+ // + " \"repeatedInt32\": [12345,]\n"
+ // + "}", builder);
+ // fail("Exception is expected.");
+ // } catch (IOException e) {
+ // // Expected.
+ // }
+ }
+
+ public void testParserRejectInvalidBase64() throws Exception {
+ assertRejects("optionalBytes", "!@#$");
+ }
+
+ public void testParserAcceptBase64Variants() throws Exception {
+ assertAccepts("optionalBytes", "AQI");
+ }
+
+ public void testParserRejectInvalidEnumValue() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ mergeFromJson("{\n" + " \"optionalNestedEnum\": \"XXX\"\n" + "}", builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserUnknownFields() throws Exception {
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}";
+ JsonFormat.parser().merge(json, builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ public void testParserIgnoringUnknownFields() throws Exception {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ String json = "{\n" + " \"unknownField\": \"XXX\"\n" + "}";
+ JsonFormat.parser().ignoringUnknownFields().merge(json, builder);
+ }
+
+ public void testCustomJsonName() throws Exception {
+ TestCustomJsonName message = TestCustomJsonName.newBuilder().setValue(12345).build();
+ assertEquals("{\n" + " \"@value\": 12345\n" + "}", JsonFormat.printer().print(message));
+ assertRoundTripEquals(message);
+ }
+
+ public void testDefaultGsonDoesNotHtmlEscape() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("=").build();
+ assertEquals(
+ "{\n" + " \"optionalString\": \"=\"" + "\n}", JsonFormat.printer().print(message));
+ }
+
+ public void testIncludingDefaultValueFields() throws Exception {
+ TestAllTypes message = TestAllTypes.getDefaultInstance();
+ assertEquals("{\n}", JsonFormat.printer().print(message));
+ assertEquals(
+ "{\n"
+ + " \"optionalInt32\": 0,\n"
+ + " \"optionalInt64\": \"0\",\n"
+ + " \"optionalUint32\": 0,\n"
+ + " \"optionalUint64\": \"0\",\n"
+ + " \"optionalSint32\": 0,\n"
+ + " \"optionalSint64\": \"0\",\n"
+ + " \"optionalFixed32\": 0,\n"
+ + " \"optionalFixed64\": \"0\",\n"
+ + " \"optionalSfixed32\": 0,\n"
+ + " \"optionalSfixed64\": \"0\",\n"
+ + " \"optionalFloat\": 0.0,\n"
+ + " \"optionalDouble\": 0.0,\n"
+ + " \"optionalBool\": false,\n"
+ + " \"optionalString\": \"\",\n"
+ + " \"optionalBytes\": \"\",\n"
+ + " \"optionalNestedEnum\": \"FOO\",\n"
+ + " \"repeatedInt32\": [],\n"
+ + " \"repeatedInt64\": [],\n"
+ + " \"repeatedUint32\": [],\n"
+ + " \"repeatedUint64\": [],\n"
+ + " \"repeatedSint32\": [],\n"
+ + " \"repeatedSint64\": [],\n"
+ + " \"repeatedFixed32\": [],\n"
+ + " \"repeatedFixed64\": [],\n"
+ + " \"repeatedSfixed32\": [],\n"
+ + " \"repeatedSfixed64\": [],\n"
+ + " \"repeatedFloat\": [],\n"
+ + " \"repeatedDouble\": [],\n"
+ + " \"repeatedBool\": [],\n"
+ + " \"repeatedString\": [],\n"
+ + " \"repeatedBytes\": [],\n"
+ + " \"repeatedNestedMessage\": [],\n"
+ + " \"repeatedNestedEnum\": []\n"
+ + "}",
+ JsonFormat.printer().includingDefaultValueFields().print(message));
+
+ TestMap mapMessage = TestMap.getDefaultInstance();
+ assertEquals("{\n}", JsonFormat.printer().print(mapMessage));
+ assertEquals(
+ "{\n"
+ + " \"int32ToInt32Map\": {\n"
+ + " },\n"
+ + " \"int64ToInt32Map\": {\n"
+ + " },\n"
+ + " \"uint32ToInt32Map\": {\n"
+ + " },\n"
+ + " \"uint64ToInt32Map\": {\n"
+ + " },\n"
+ + " \"sint32ToInt32Map\": {\n"
+ + " },\n"
+ + " \"sint64ToInt32Map\": {\n"
+ + " },\n"
+ + " \"fixed32ToInt32Map\": {\n"
+ + " },\n"
+ + " \"fixed64ToInt32Map\": {\n"
+ + " },\n"
+ + " \"sfixed32ToInt32Map\": {\n"
+ + " },\n"
+ + " \"sfixed64ToInt32Map\": {\n"
+ + " },\n"
+ + " \"boolToInt32Map\": {\n"
+ + " },\n"
+ + " \"stringToInt32Map\": {\n"
+ + " },\n"
+ + " \"int32ToInt64Map\": {\n"
+ + " },\n"
+ + " \"int32ToUint32Map\": {\n"
+ + " },\n"
+ + " \"int32ToUint64Map\": {\n"
+ + " },\n"
+ + " \"int32ToSint32Map\": {\n"
+ + " },\n"
+ + " \"int32ToSint64Map\": {\n"
+ + " },\n"
+ + " \"int32ToFixed32Map\": {\n"
+ + " },\n"
+ + " \"int32ToFixed64Map\": {\n"
+ + " },\n"
+ + " \"int32ToSfixed32Map\": {\n"
+ + " },\n"
+ + " \"int32ToSfixed64Map\": {\n"
+ + " },\n"
+ + " \"int32ToFloatMap\": {\n"
+ + " },\n"
+ + " \"int32ToDoubleMap\": {\n"
+ + " },\n"
+ + " \"int32ToBoolMap\": {\n"
+ + " },\n"
+ + " \"int32ToStringMap\": {\n"
+ + " },\n"
+ + " \"int32ToBytesMap\": {\n"
+ + " },\n"
+ + " \"int32ToMessageMap\": {\n"
+ + " },\n"
+ + " \"int32ToEnumMap\": {\n"
+ + " }\n"
+ + "}",
+ JsonFormat.printer().includingDefaultValueFields().print(mapMessage));
+
+ TestOneof oneofMessage = TestOneof.getDefaultInstance();
+ assertEquals("{\n}", JsonFormat.printer().print(oneofMessage));
+ assertEquals("{\n}", JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
+
+ oneofMessage = TestOneof.newBuilder().setOneofInt32(42).build();
+ assertEquals("{\n \"oneofInt32\": 42\n}",
+ JsonFormat.printer().print(oneofMessage));
+ assertEquals("{\n \"oneofInt32\": 42\n}",
+ JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
+
+ TestOneof.Builder oneofBuilder = TestOneof.newBuilder();
+ mergeFromJson("{\n" + " \"oneofNullValue\": null \n" + "}", oneofBuilder);
+ oneofMessage = oneofBuilder.build();
+ assertEquals("{\n \"oneofNullValue\": null\n}", JsonFormat.printer().print(oneofMessage));
+ assertEquals("{\n \"oneofNullValue\": null\n}",
+ JsonFormat.printer().includingDefaultValueFields().print(oneofMessage));
+ }
+
+ public void testPreservingProtoFieldNames() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
+ assertEquals("{\n" + " \"optionalInt32\": 12345\n" + "}", JsonFormat.printer().print(message));
+ assertEquals(
+ "{\n" + " \"optional_int32\": 12345\n" + "}",
+ JsonFormat.printer().preservingProtoFieldNames().print(message));
+
+ // The json_name field option is ignored when configured to use original proto field names.
+ TestCustomJsonName messageWithCustomJsonName =
+ TestCustomJsonName.newBuilder().setValue(12345).build();
+ assertEquals(
+ "{\n" + " \"value\": 12345\n" + "}",
+ JsonFormat.printer().preservingProtoFieldNames().print(messageWithCustomJsonName));
+
+ // Parsers accept both original proto field names and lowerCamelCase names.
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ JsonFormat.parser().merge("{\"optionalInt32\": 12345}", builder);
+ assertEquals(12345, builder.getOptionalInt32());
+ builder.clear();
+ JsonFormat.parser().merge("{\"optional_int32\": 54321}", builder);
+ assertEquals(54321, builder.getOptionalInt32());
+ }
+
+ public void testOmittingInsignificantWhiteSpace() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(12345).build();
+ assertEquals(
+ "{" + "\"optionalInt32\":12345" + "}",
+ JsonFormat.printer().omittingInsignificantWhitespace().print(message));
+ TestAllTypes message1 = TestAllTypes.getDefaultInstance();
+ assertEquals("{}", JsonFormat.printer().omittingInsignificantWhitespace().print(message1));
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ setAllFields(builder);
+ TestAllTypes message2 = builder.build();
+ assertEquals(
+ "{"
+ + "\"optionalInt32\":1234,"
+ + "\"optionalInt64\":\"1234567890123456789\","
+ + "\"optionalUint32\":5678,"
+ + "\"optionalUint64\":\"2345678901234567890\","
+ + "\"optionalSint32\":9012,"
+ + "\"optionalSint64\":\"3456789012345678901\","
+ + "\"optionalFixed32\":3456,"
+ + "\"optionalFixed64\":\"4567890123456789012\","
+ + "\"optionalSfixed32\":7890,"
+ + "\"optionalSfixed64\":\"5678901234567890123\","
+ + "\"optionalFloat\":1.5,"
+ + "\"optionalDouble\":1.25,"
+ + "\"optionalBool\":true,"
+ + "\"optionalString\":\"Hello world!\","
+ + "\"optionalBytes\":\"AAEC\","
+ + "\"optionalNestedMessage\":{"
+ + "\"value\":100"
+ + "},"
+ + "\"optionalNestedEnum\":\"BAR\","
+ + "\"repeatedInt32\":[1234,234],"
+ + "\"repeatedInt64\":[\"1234567890123456789\",\"234567890123456789\"],"
+ + "\"repeatedUint32\":[5678,678],"
+ + "\"repeatedUint64\":[\"2345678901234567890\",\"345678901234567890\"],"
+ + "\"repeatedSint32\":[9012,10],"
+ + "\"repeatedSint64\":[\"3456789012345678901\",\"456789012345678901\"],"
+ + "\"repeatedFixed32\":[3456,456],"
+ + "\"repeatedFixed64\":[\"4567890123456789012\",\"567890123456789012\"],"
+ + "\"repeatedSfixed32\":[7890,890],"
+ + "\"repeatedSfixed64\":[\"5678901234567890123\",\"678901234567890123\"],"
+ + "\"repeatedFloat\":[1.5,11.5],"
+ + "\"repeatedDouble\":[1.25,11.25],"
+ + "\"repeatedBool\":[true,true],"
+ + "\"repeatedString\":[\"Hello world!\",\"ello world!\"],"
+ + "\"repeatedBytes\":[\"AAEC\",\"AQI=\"],"
+ + "\"repeatedNestedMessage\":[{"
+ + "\"value\":100"
+ + "},{"
+ + "\"value\":200"
+ + "}],"
+ + "\"repeatedNestedEnum\":[\"BAR\",\"BAZ\"]"
+ + "}",
+ toCompactJsonString(message2));
+ }
+
+ // Regression test for b/29892357
+ public void testEmptyWrapperTypesInAny() throws Exception {
+ JsonFormat.TypeRegistry registry =
+ JsonFormat.TypeRegistry.newBuilder().add(TestAllTypes.getDescriptor()).build();
+ JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(registry);
+
+ Any.Builder builder = Any.newBuilder();
+ parser.merge(
+ "{\n"
+ + " \"@type\": \"type.googleapis.com/google.protobuf.BoolValue\",\n"
+ + " \"value\": false\n"
+ + "}\n",
+ builder);
+ Any any = builder.build();
+ assertEquals(0, any.getValue().size());
+ }
+
+ public void testRecursionLimit() throws Exception {
+ String input =
+ "{\n"
+ + " \"nested\": {\n"
+ + " \"nested\": {\n"
+ + " \"nested\": {\n"
+ + " \"nested\": {\n"
+ + " \"value\": 1234\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + " }\n"
+ + "}\n";
+
+ JsonFormat.Parser parser = JsonFormat.parser();
+ TestRecursive.Builder builder = TestRecursive.newBuilder();
+ parser.merge(input, builder);
+ TestRecursive message = builder.build();
+ assertEquals(1234, message.getNested().getNested().getNested().getNested().getValue());
+
+ parser = JsonFormat.parser().usingRecursionLimit(3);
+ builder = TestRecursive.newBuilder();
+ try {
+ parser.merge(input, builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+
+ // Test that we are not leaking out JSON exceptions.
+ public void testJsonException() throws Exception {
+ InputStream throwingInputStream = new InputStream() {
+ public int read() throws IOException {
+ throw new IOException("12345");
+ }
+ };
+ InputStreamReader throwingReader = new InputStreamReader(throwingInputStream);
+ // When the underlying reader throws IOException, JsonFormat should forward
+ // through this IOException.
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ JsonFormat.parser().merge(throwingReader, builder);
+ fail("Exception is expected.");
+ } catch (IOException e) {
+ assertEquals("12345", e.getMessage());
+ }
+
+ Reader invalidJsonReader = new StringReader("{ xxx - yyy }");
+ // When the JSON parser throws parser exceptions, JsonFormat should turn
+ // that into InvalidProtocolBufferException.
+ try {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ JsonFormat.parser().merge(invalidJsonReader, builder);
+ fail("Exception is expected.");
+ } catch (InvalidProtocolBufferException e) {
+ // Expected.
+ }
+ }
+}
diff --git a/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
new file mode 100644
index 0000000000..5af83d88e6
--- /dev/null
+++ b/third_party/protobuf/java/util/src/test/java/com/google/protobuf/util/TimeUtilTest.java
@@ -0,0 +1,498 @@
+// 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.util;
+
+import com.google.protobuf.Duration;
+import com.google.protobuf.Timestamp;
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.List;
+import junit.framework.TestCase;
+import org.junit.Assert;
+
+/** Unit tests for {@link TimeUtil}. */
+public class TimeUtilTest extends TestCase {
+ public void testTimestampStringFormat() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+ assertEquals(TimeUtil.TIMESTAMP_SECONDS_MIN, start.getSeconds());
+ assertEquals(0, start.getNanos());
+ assertEquals(TimeUtil.TIMESTAMP_SECONDS_MAX, end.getSeconds());
+ assertEquals(999999999, end.getNanos());
+ assertEquals("0001-01-01T00:00:00Z", TimeUtil.toString(start));
+ assertEquals("9999-12-31T23:59:59.999999999Z", TimeUtil.toString(end));
+
+ Timestamp value = TimeUtil.parseTimestamp("1970-01-01T00:00:00Z");
+ assertEquals(0, value.getSeconds());
+ assertEquals(0, value.getNanos());
+
+ // Test negative timestamps.
+ value = TimeUtil.parseTimestamp("1969-12-31T23:59:59.999Z");
+ assertEquals(-1, value.getSeconds());
+ // Nano part is in the range of [0, 999999999] for Timestamp.
+ assertEquals(999000000, value.getNanos());
+
+ // Test that 3, 6, or 9 digits are used for the fractional part.
+ value = Timestamp.newBuilder().setNanos(10).build();
+ assertEquals("1970-01-01T00:00:00.000000010Z", TimeUtil.toString(value));
+ value = Timestamp.newBuilder().setNanos(10000).build();
+ assertEquals("1970-01-01T00:00:00.000010Z", TimeUtil.toString(value));
+ value = Timestamp.newBuilder().setNanos(10000000).build();
+ assertEquals("1970-01-01T00:00:00.010Z", TimeUtil.toString(value));
+
+ // Test that parsing accepts timezone offsets.
+ value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010+08:00");
+ assertEquals("1969-12-31T16:00:00.010Z", TimeUtil.toString(value));
+ value = TimeUtil.parseTimestamp("1970-01-01T00:00:00.010-08:00");
+ assertEquals("1970-01-01T08:00:00.010Z", TimeUtil.toString(value));
+ }
+
+ private volatile boolean stopParsingThreads = false;
+ private volatile String errorMessage = "";
+
+ private class ParseTimestampThread extends Thread {
+ private final String[] strings;
+ private final Timestamp[] values;
+
+ public ParseTimestampThread(String[] strings, Timestamp[] values) {
+ this.strings = strings;
+ this.values = values;
+ }
+
+ @Override
+ public void run() {
+ int index = 0;
+ while (!stopParsingThreads) {
+ Timestamp result;
+ try {
+ result = TimeUtil.parseTimestamp(strings[index]);
+ } catch (ParseException e) {
+ errorMessage = "Failed to parse timestamp: " + strings[index];
+ break;
+ }
+ if (result.getSeconds() != values[index].getSeconds()
+ || result.getNanos() != values[index].getNanos()) {
+ errorMessage =
+ "Actual result: " + result.toString() + ", expected: " + values[index].toString();
+ break;
+ }
+ index = (index + 1) % strings.length;
+ }
+ }
+ }
+
+ public void testTimestampConcurrentParsing() throws Exception {
+ String[] timestampStrings =
+ new String[] {
+ "0001-01-01T00:00:00Z",
+ "9999-12-31T23:59:59.999999999Z",
+ "1970-01-01T00:00:00Z",
+ "1969-12-31T23:59:59.999Z",
+ };
+ Timestamp[] timestampValues = new Timestamp[timestampStrings.length];
+ for (int i = 0; i < timestampStrings.length; i++) {
+ timestampValues[i] = TimeUtil.parseTimestamp(timestampStrings[i]);
+ }
+
+ final int THREAD_COUNT = 16;
+ final int RUNNING_TIME = 5000; // in milliseconds.
+ final List<Thread> threads = new ArrayList<Thread>();
+
+ stopParsingThreads = false;
+ errorMessage = "";
+ for (int i = 0; i < THREAD_COUNT; i++) {
+ Thread thread = new ParseTimestampThread(timestampStrings, timestampValues);
+ thread.start();
+ threads.add(thread);
+ }
+ Thread.sleep(RUNNING_TIME);
+ stopParsingThreads = true;
+ for (Thread thread : threads) {
+ thread.join();
+ }
+ Assert.assertEquals("", errorMessage);
+ }
+
+ public void testTimetampInvalidFormat() throws Exception {
+ try {
+ // Value too small.
+ Timestamp value =
+ Timestamp.newBuilder().setSeconds(TimeUtil.TIMESTAMP_SECONDS_MIN - 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ Timestamp value =
+ Timestamp.newBuilder().setSeconds(TimeUtil.TIMESTAMP_SECONDS_MAX + 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Timestamp value = Timestamp.newBuilder().setNanos(-1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Timestamp value = Timestamp.newBuilder().setNanos(1000000000).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value to small.
+ TimeUtil.parseTimestamp("0000-01-01T00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Value to large.
+ TimeUtil.parseTimestamp("10000-01-01T00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing 'T'.
+ TimeUtil.parseTimestamp("1970-01-01 00:00:00Z");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing 'Z'.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid offset.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00+0000");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Trailing text.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00Z0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanosecond value.
+ TimeUtil.parseTimestamp("1970-01-01T00:00:00.ABCZ");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+ }
+
+ public void testDurationStringFormat() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+ Duration duration = TimeUtil.distance(start, end);
+ assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+ duration = TimeUtil.distance(end, start);
+ assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+
+ // Generated output should contain 3, 6, or 9 fractional digits.
+ duration = Duration.newBuilder().setSeconds(1).build();
+ assertEquals("1s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10000000).build();
+ assertEquals("0.010s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10000).build();
+ assertEquals("0.000010s", TimeUtil.toString(duration));
+ duration = Duration.newBuilder().setNanos(10).build();
+ assertEquals("0.000000010s", TimeUtil.toString(duration));
+
+ // Parsing accepts an fractional digits as long as they fit into nano
+ // precision.
+ duration = TimeUtil.parseDuration("0.1s");
+ assertEquals(100000000, duration.getNanos());
+ duration = TimeUtil.parseDuration("0.0001s");
+ assertEquals(100000, duration.getNanos());
+ duration = TimeUtil.parseDuration("0.0000001s");
+ assertEquals(100, duration.getNanos());
+
+ // Duration must support range from -315,576,000,000s to +315576000000s
+ // which includes negative values.
+ duration = TimeUtil.parseDuration("315576000000.999999999s");
+ assertEquals(315576000000L, duration.getSeconds());
+ assertEquals(999999999, duration.getNanos());
+ duration = TimeUtil.parseDuration("-315576000000.999999999s");
+ assertEquals(-315576000000L, duration.getSeconds());
+ assertEquals(-999999999, duration.getNanos());
+ }
+
+ public void testDurationInvalidFormat() throws Exception {
+ try {
+ // Value too small.
+ Duration value = Duration.newBuilder().setSeconds(TimeUtil.DURATION_SECONDS_MIN - 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ Duration value = Duration.newBuilder().setSeconds(TimeUtil.DURATION_SECONDS_MAX + 1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Duration value = Duration.newBuilder().setSeconds(1).setNanos(-1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid nanos value.
+ Duration value = Duration.newBuilder().setSeconds(-1).setNanos(1).build();
+ TimeUtil.toString(value);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too small.
+ TimeUtil.parseDuration("-315576000001s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Value too large.
+ TimeUtil.parseDuration("315576000001s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Empty.
+ TimeUtil.parseDuration("");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Missing "s".
+ TimeUtil.parseDuration("0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid trailing data.
+ TimeUtil.parseDuration("0s0");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+
+ try {
+ // Invalid prefix.
+ TimeUtil.parseDuration("--1s");
+ Assert.fail("Exception is expected.");
+ } catch (ParseException e) {
+ // Expected.
+ }
+ }
+
+ public void testTimestampConversion() throws Exception {
+ Timestamp timestamp = TimeUtil.parseTimestamp("1970-01-01T00:00:01.111111111Z");
+ assertEquals(1111111111, TimeUtil.toNanos(timestamp));
+ assertEquals(1111111, TimeUtil.toMicros(timestamp));
+ assertEquals(1111, TimeUtil.toMillis(timestamp));
+ timestamp = TimeUtil.createTimestampFromNanos(1111111111);
+ assertEquals("1970-01-01T00:00:01.111111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMicros(1111111);
+ assertEquals("1970-01-01T00:00:01.111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMillis(1111);
+ assertEquals("1970-01-01T00:00:01.111Z", TimeUtil.toString(timestamp));
+
+ timestamp = TimeUtil.parseTimestamp("1969-12-31T23:59:59.111111111Z");
+ assertEquals(-888888889, TimeUtil.toNanos(timestamp));
+ assertEquals(-888889, TimeUtil.toMicros(timestamp));
+ assertEquals(-889, TimeUtil.toMillis(timestamp));
+ timestamp = TimeUtil.createTimestampFromNanos(-888888889);
+ assertEquals("1969-12-31T23:59:59.111111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMicros(-888889);
+ assertEquals("1969-12-31T23:59:59.111111Z", TimeUtil.toString(timestamp));
+ timestamp = TimeUtil.createTimestampFromMillis(-889);
+ assertEquals("1969-12-31T23:59:59.111Z", TimeUtil.toString(timestamp));
+ }
+
+ public void testDurationConversion() throws Exception {
+ Duration duration = TimeUtil.parseDuration("1.111111111s");
+ assertEquals(1111111111, TimeUtil.toNanos(duration));
+ assertEquals(1111111, TimeUtil.toMicros(duration));
+ assertEquals(1111, TimeUtil.toMillis(duration));
+ duration = TimeUtil.createDurationFromNanos(1111111111);
+ assertEquals("1.111111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMicros(1111111);
+ assertEquals("1.111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMillis(1111);
+ assertEquals("1.111s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.parseDuration("-1.111111111s");
+ assertEquals(-1111111111, TimeUtil.toNanos(duration));
+ assertEquals(-1111111, TimeUtil.toMicros(duration));
+ assertEquals(-1111, TimeUtil.toMillis(duration));
+ duration = TimeUtil.createDurationFromNanos(-1111111111);
+ assertEquals("-1.111111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMicros(-1111111);
+ assertEquals("-1.111111s", TimeUtil.toString(duration));
+ duration = TimeUtil.createDurationFromMillis(-1111);
+ assertEquals("-1.111s", TimeUtil.toString(duration));
+ }
+
+ public void testTimeOperations() throws Exception {
+ Timestamp start = TimeUtil.parseTimestamp("0001-01-01T00:00:00Z");
+ Timestamp end = TimeUtil.parseTimestamp("9999-12-31T23:59:59.999999999Z");
+
+ Duration duration = TimeUtil.distance(start, end);
+ assertEquals("315537897599.999999999s", TimeUtil.toString(duration));
+ Timestamp value = TimeUtil.add(start, duration);
+ assertEquals(end, value);
+ value = TimeUtil.subtract(end, duration);
+ assertEquals(start, value);
+
+ duration = TimeUtil.distance(end, start);
+ assertEquals("-315537897599.999999999s", TimeUtil.toString(duration));
+ value = TimeUtil.add(end, duration);
+ assertEquals(start, value);
+ value = TimeUtil.subtract(start, duration);
+ assertEquals(end, value);
+
+ // Result is larger than Long.MAX_VALUE.
+ try {
+ duration = TimeUtil.parseDuration("315537897599.999999999s");
+ duration = TimeUtil.multiply(duration, 315537897599.999999999);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Result is lesser than Long.MIN_VALUE.
+ try {
+ duration = TimeUtil.parseDuration("315537897599.999999999s");
+ duration = TimeUtil.multiply(duration, -315537897599.999999999);
+ Assert.fail("Exception is expected.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ duration = TimeUtil.parseDuration("-1.125s");
+ duration = TimeUtil.divide(duration, 2.0);
+ assertEquals("-0.562500s", TimeUtil.toString(duration));
+ duration = TimeUtil.multiply(duration, 2.0);
+ assertEquals("-1.125s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.add(duration, duration);
+ assertEquals("-2.250s", TimeUtil.toString(duration));
+
+ duration = TimeUtil.subtract(duration, TimeUtil.parseDuration("-1s"));
+ assertEquals("-1.250s", TimeUtil.toString(duration));
+
+ // Multiplications (with results larger than Long.MAX_VALUE in nanoseconds).
+ duration = TimeUtil.parseDuration("0.999999999s");
+ assertEquals(
+ "315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+ duration = TimeUtil.parseDuration("-0.999999999s");
+ assertEquals(
+ "-315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, 315576000000L)));
+ assertEquals(
+ "315575999684.424s", TimeUtil.toString(TimeUtil.multiply(duration, -315576000000L)));
+
+ // Divisions (with values larger than Long.MAX_VALUE in nanoseconds).
+ Duration d1 = TimeUtil.parseDuration("315576000000s");
+ Duration d2 = TimeUtil.subtract(d1, TimeUtil.createDurationFromNanos(1));
+ assertEquals(1, TimeUtil.divide(d1, d2));
+ assertEquals(0, TimeUtil.divide(d2, d1));
+ assertEquals("0.000000001s", TimeUtil.toString(TimeUtil.remainder(d1, d2)));
+ assertEquals("315575999999.999999999s", TimeUtil.toString(TimeUtil.remainder(d2, d1)));
+
+ // Divisions involving negative values.
+ //
+ // (-5) / 2 = -2, remainder = -1
+ d1 = TimeUtil.parseDuration("-5s");
+ d2 = TimeUtil.parseDuration("2s");
+ assertEquals(-2, TimeUtil.divide(d1, d2));
+ assertEquals(-2, TimeUtil.divide(d1, 2).getSeconds());
+ assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+ // (-5) / (-2) = 2, remainder = -1
+ d1 = TimeUtil.parseDuration("-5s");
+ d2 = TimeUtil.parseDuration("-2s");
+ assertEquals(2, TimeUtil.divide(d1, d2));
+ assertEquals(2, TimeUtil.divide(d1, -2).getSeconds());
+ assertEquals(-1, TimeUtil.remainder(d1, d2).getSeconds());
+ // 5 / (-2) = -2, remainder = 1
+ d1 = TimeUtil.parseDuration("5s");
+ d2 = TimeUtil.parseDuration("-2s");
+ assertEquals(-2, TimeUtil.divide(d1, d2));
+ assertEquals(-2, TimeUtil.divide(d1, -2).getSeconds());
+ assertEquals(1, TimeUtil.remainder(d1, d2).getSeconds());
+ }
+}
diff --git a/third_party/protobuf/java/util/src/test/proto/com/google/protobuf/util/json_test.proto b/third_party/protobuf/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
new file mode 100644
index 0000000000..d1248cfb71
--- /dev/null
+++ b/third_party/protobuf/java/util/src/test/proto/com/google/protobuf/util/json_test.proto
@@ -0,0 +1,178 @@
+// 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.
+
+syntax = "proto3";
+
+package json_test;
+
+option java_package = "com.google.protobuf.util";
+option java_outer_classname = "JsonTestProto";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/wrappers.proto";
+import "google/protobuf/timestamp.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+ message NestedMessage {
+ int32 value = 1;
+ }
+
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+ NestedMessage optional_nested_message = 18;
+ NestedEnum optional_nested_enum = 21;
+
+ // Repeated
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ repeated NestedMessage repeated_nested_message = 48;
+ repeated NestedEnum repeated_nested_enum = 51;
+}
+
+message TestOneof {
+ oneof oneof_field {
+ int32 oneof_int32 = 1;
+ TestAllTypes.NestedMessage oneof_nested_message = 2;
+ google.protobuf.NullValue oneof_null_value = 3;
+ }
+}
+
+message TestMap {
+ // Instead of testing all combinations (too many), we only make sure all
+ // valid types have been used at least in one field as key and in one
+ // field as value.
+ map<int32, int32> int32_to_int32_map = 1;
+ map<int64, int32> int64_to_int32_map = 2;
+ map<uint32, int32> uint32_to_int32_map = 3;
+ map<uint64, int32> uint64_to_int32_map = 4;
+ map<sint32, int32> sint32_to_int32_map = 5;
+ map<sint64, int32> sint64_to_int32_map = 6;
+ map<fixed32, int32> fixed32_to_int32_map = 7;
+ map<fixed64, int32> fixed64_to_int32_map = 8;
+ map<sfixed32, int32> sfixed32_to_int32_map = 9;
+ map<sfixed64, int32> sfixed64_to_int32_map = 10;
+ map<bool, int32> bool_to_int32_map = 11;
+ map<string, int32> string_to_int32_map = 12;
+
+ map<int32, int64> int32_to_int64_map = 101;
+ map<int32, uint32> int32_to_uint32_map = 102;
+ map<int32, uint64> int32_to_uint64_map = 103;
+ map<int32, sint32> int32_to_sint32_map = 104;
+ map<int32, sint64> int32_to_sint64_map = 105;
+ map<int32, fixed32> int32_to_fixed32_map = 106;
+ map<int32, fixed64> int32_to_fixed64_map = 107;
+ map<int32, sfixed32> int32_to_sfixed32_map = 108;
+ map<int32, sfixed64> int32_to_sfixed64_map = 109;
+ map<int32, float> int32_to_float_map = 110;
+ map<int32, double> int32_to_double_map = 111;
+ map<int32, bool> int32_to_bool_map = 112;
+ map<int32, string> int32_to_string_map = 113;
+ map<int32, bytes> int32_to_bytes_map = 114;
+ map<int32, TestAllTypes.NestedMessage> int32_to_message_map = 115;
+ map<int32, TestAllTypes.NestedEnum> int32_to_enum_map = 116;
+}
+
+message TestWrappers {
+ google.protobuf.Int32Value int32_value = 1;
+ google.protobuf.UInt32Value uint32_value = 2;
+ google.protobuf.Int64Value int64_value = 3;
+ google.protobuf.UInt64Value uint64_value = 4;
+ google.protobuf.FloatValue float_value = 5;
+ google.protobuf.DoubleValue double_value = 6;
+ google.protobuf.BoolValue bool_value = 7;
+ google.protobuf.StringValue string_value = 8;
+ google.protobuf.BytesValue bytes_value = 9;
+}
+
+message TestTimestamp {
+ google.protobuf.Timestamp timestamp_value = 1;
+}
+
+message TestDuration {
+ google.protobuf.Duration duration_value = 1;
+}
+
+message TestFieldMask {
+ google.protobuf.FieldMask field_mask_value = 1;
+}
+
+message TestStruct {
+ google.protobuf.Struct struct_value = 1;
+ google.protobuf.Value value = 2;
+ google.protobuf.ListValue list_value = 3;
+}
+
+message TestAny {
+ google.protobuf.Any any_value = 1;
+ map<string, google.protobuf.Any> any_map = 2;
+}
+
+message TestCustomJsonName {
+ int32 value = 1 [json_name = "@value"];
+}
+
+message TestRecursive {
+ int32 value = 1;
+ TestRecursive nested = 2;
+}