aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorHao Nguyen <haon@google.com>2019-04-05 16:39:18 -0700
committerHao Nguyen <haon@google.com>2019-04-05 16:39:18 -0700
commita48a574f7e890436363ca8ac71d866252b216052 (patch)
tree7829f1b60e31da551f22a3df4756bfef0b7f9096 /java
parent3a3956e8a258784461270961c6577341356bce52 (diff)
downloadplatform_external_protobuf-a48a574f7e890436363ca8ac71d866252b216052.tar.gz
platform_external_protobuf-a48a574f7e890436363ca8ac71d866252b216052.tar.bz2
platform_external_protobuf-a48a574f7e890436363ca8ac71d866252b216052.zip
Down integrate to Github
Diffstat (limited to 'java')
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java50
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/AllocatedBuffer.java263
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ArrayDecoders.java1076
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/BinaryReader.java1729
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/BinaryWriter.java3071
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/BufferAllocator.java64
-rw-r--r--java/core/src/main/java/com/google/protobuf/ByteString.java32
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedInputStream.java57
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java1333
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedOutputStream.java113
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java691
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java693
-rw-r--r--java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java13
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ExtensionSchema.java98
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java547
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java541
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ExtensionSchemas.java56
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/FieldInfo.java577
-rw-r--r--java/core/src/main/java/com/google/protobuf/FieldSet.java11
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/FieldType.java346
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java65
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java995
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java23
-rw-r--r--java/core/src/main/java/com/google/protobuf/Internal.java18
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/JavaType.java76
-rw-r--r--java/core/src/main/java/com/google/protobuf/LazyFieldLite.java12
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ListFieldSchema.java190
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java172
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MapFieldSchema.java63
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java112
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java107
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MapFieldSchemas.java53
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MessageInfo.java43
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MessageInfoFactory.java41
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MessageSchema.java5886
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/MessageSetSchema.java392
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/NewInstanceSchema.java36
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java39
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java39
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java53
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/OneofInfo.java66
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ProtoSyntax.java38
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/Protobuf.java152
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/ProtobufLists.java94
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/RawMessageInfo.java226
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/Reader.java379
-rw-r--r--java/core/src/main/java/com/google/protobuf/RopeByteString.java5
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/Schema.java85
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/SchemaFactory.java38
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/SchemaUtil.java991
-rw-r--r--java/core/src/main/java/com/google/protobuf/SmallSortedMap.java65
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java167
-rw-r--r--java/core/src/main/java/com/google/protobuf/TextFormat.java54
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java133
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java79
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java66
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java140
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java132
-rwxr-xr-xjava/core/src/main/java/com/google/protobuf/Writer.java219
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java199
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java224
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java143
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java151
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java157
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java236
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java90
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java65
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/CodedAdapterTest.java110
-rw-r--r--java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java56
-rw-r--r--java/core/src/test/java/com/google/protobuf/DescriptorsTest.java21
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java40
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java113
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java189
-rw-r--r--java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java43
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/MapLiteTest.java894
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/PackedFieldTest.java232
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/ParserLiteTest.java191
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java171
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java49
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java555
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java892
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java558
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java49
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java111
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java49
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java450
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java506
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java452
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java816
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java48
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/TestSchemas.java94
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/TestSchemasLite.java103
-rw-r--r--java/core/src/test/java/com/google/protobuf/TextFormatTest.java21
-rw-r--r--java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java601
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Utf8Test.java232
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/Utf8Utils.java193
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java1023
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java61
-rwxr-xr-xjava/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java61
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto45
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto47
-rw-r--r--java/core/src/test/proto/com/google/protobuf/nested_extension.proto4
-rw-r--r--java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto4
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/packed_field_test.proto76
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/proto2_message.proto429
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto422
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/proto3_message.proto326
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto319
-rwxr-xr-xjava/core/src/test/proto/com/google/protobuf/wrappers_test.proto49
-rwxr-xr-x[-rw-r--r--]java/lite/src/test/java/com/google/protobuf/LiteTest.java (renamed from java/core/src/test/java/com/google/protobuf/LiteTest.java)22
-rwxr-xr-xjava/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java1327
-rw-r--r--java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java14
112 files changed, 34654 insertions, 1584 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 172057509..ba0138af5 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -106,6 +106,56 @@ public abstract class AbstractMessageLite<
}
+ @ExperimentalApi
+ protected final boolean isInitializedInternal() {
+ return Protobuf.getInstance().schemaFor(this).isInitialized(this);
+ }
+
+ @ExperimentalApi
+ protected final int getSerializedSizeInternal() {
+ return Protobuf.getInstance().schemaFor(this).getSerializedSize(this);
+ }
+
+ int getSerializedSize(Schema schema) {
+ int memoizedSerializedSize = getMemoizedSerializedSize();
+ if (memoizedSerializedSize == -1) {
+ memoizedSerializedSize = schema.getSerializedSize(this);
+ setMemoizedSerializedSize(memoizedSerializedSize);
+ }
+ return memoizedSerializedSize;
+ }
+
+ @ExperimentalApi
+ protected final void writeToInternal(CodedOutputStream output) throws IOException {
+ Protobuf.getInstance()
+ .schemaFor(getClassInternal())
+ .writeTo(this, CodedOutputStreamWriter.forCodedOutput(output));
+ }
+
+ @ExperimentalApi
+ protected void mergeFromInternal(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
+ try {
+ Protobuf.getInstance()
+ .schemaFor(getClassInternal())
+ .mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
+ } catch (InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (IOException e) {
+ throw new InvalidProtocolBufferException(e).setUnfinishedMessage(this);
+ }
+ }
+
+ @ExperimentalApi
+ protected void makeImmutableInternal() {
+ Protobuf.getInstance().schemaFor(getClassInternal()).makeImmutable(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<AbstractMessageLite<MessageType, BuilderType>> getClassInternal() {
+ return (Class<AbstractMessageLite<MessageType, BuilderType>>) getClass();
+ }
+
/** Package private helper method for AbstractParser to create UninitializedMessageException. */
UninitializedMessageException newUninitializedMessageException() {
return new UninitializedMessageException(this);
diff --git a/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java
new file mode 100755
index 000000000..a01a6c1a8
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java
@@ -0,0 +1,263 @@
+// 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.nio.ByteBuffer;
+
+/**
+ * A buffer that was allocated by a {@link BufferAllocator}. For every buffer, it is guaranteed that
+ * at least one of {@link #hasArray()} or {@link #hasNioBuffer()} will be {@code true}.
+ */
+@ExperimentalApi
+abstract class AllocatedBuffer {
+ /**
+ * Indicates whether this buffer contains a backing {@link ByteBuffer} (i.e. it is safe to call
+ * {@link #nioBuffer()}).
+ */
+ public abstract boolean hasNioBuffer();
+
+ /**
+ * Indicates whether this buffer contains a backing array (i.e. it is safe to call {@link
+ * #array()}).
+ */
+ public abstract boolean hasArray();
+
+ /**
+ * Returns the {@link ByteBuffer} that backs this buffer <i>(optional operation)</i>.
+ *
+ * <p>Call {@link #hasNioBuffer()} before invoking this method in order to ensure that this buffer
+ * has a backing {@link ByteBuffer}.
+ *
+ * @return The {@link ByteBuffer} that backs this buffer
+ * @throws UnsupportedOperationException If this buffer is not backed by a {@link ByteBuffer}.
+ */
+ public abstract ByteBuffer nioBuffer();
+
+ /**
+ * Returns the byte array that backs this buffer <i>(optional operation)</i>.
+ *
+ * <p>Call {@link #hasArray()} before invoking this method in order to ensure that this buffer has
+ * an accessible backing array.
+ *
+ * @return The array that backs this buffer
+ * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only
+ * @throws UnsupportedOperationException If this buffer is not backed by an accessible array
+ */
+ public abstract byte[] array();
+
+ /**
+ * Returns the offset within this buffer's backing array of the first element of the buffer
+ * <i>(optional operation)</i>.
+ *
+ * <p>If this buffer is backed by an array then {@link #position()} corresponds to the array index
+ * {@link #position()} {@code +} {@link #arrayOffset()}.
+ *
+ * <p>Invoke the {@link #hasArray hasArray} method before invoking this method in order to ensure
+ * that this buffer has an accessible backing array.
+ *
+ * @return The offset within this buffer's array of the first element of the buffer
+ * @throws java.nio.ReadOnlyBufferException If this buffer is backed by an array but is read-only
+ * @throws UnsupportedOperationException If this buffer is not backed by an accessible array
+ */
+ public abstract int arrayOffset();
+
+ /**
+ * Returns this buffer's position.
+ *
+ * @return The position of this buffer
+ */
+ public abstract int position();
+
+ /**
+ * Sets this buffer's position.
+ *
+ * @param position The new position value; must be non-negative and no larger than the current
+ * limit
+ * @return This buffer
+ * @throws IllegalArgumentException If the preconditions on {@code position} do not hold
+ */
+ public abstract AllocatedBuffer position(int position);
+
+ /**
+ * Returns this buffer's limit.
+ *
+ * @return The limit of this buffer
+ */
+ public abstract int limit();
+
+ /**
+ * Returns the number of elements between the current {@link #position()} and the {@link #limit()}
+ * .
+ *
+ * @return The number of elements remaining in this buffer
+ */
+ public abstract int remaining();
+
+ /**
+ * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer
+ * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code 0}, {@link
+ * #position()} == {@code 0} and {@link #limit()} equal to the length of {@code bytes}.
+ */
+ public static AllocatedBuffer wrap(byte[] bytes) {
+ return wrapNoCheck(bytes, 0, bytes.length);
+ }
+
+ /**
+ * Creates a new {@link AllocatedBuffer} that is backed by the given array. The returned buffer
+ * will have {@link #hasArray} == {@code true}, {@link #arrayOffset()} == {@code offset}, {@link
+ * #position()} == {@code 0} and {@link #limit()} == {@code length}.
+ */
+ public static AllocatedBuffer wrap(final byte[] bytes, final int offset, final int length) {
+ if (offset < 0 || length < 0 || (offset + length) > bytes.length) {
+ throw new IndexOutOfBoundsException(
+ String.format("bytes.length=%d, offset=%d, length=%d", bytes.length, offset, length));
+ }
+
+ return wrapNoCheck(bytes, offset, length);
+ }
+
+ /**
+ * Creates a new {@link AllocatedBuffer} that is backed by the given {@link ByteBuffer}. The
+ * returned buffer will have {@link #hasNioBuffer} == {@code true}.
+ */
+ public static AllocatedBuffer wrap(final ByteBuffer buffer) {
+ checkNotNull(buffer, "buffer");
+
+ return new AllocatedBuffer() {
+
+ @Override
+ public boolean hasNioBuffer() {
+ return true;
+ }
+
+ @Override
+ public ByteBuffer nioBuffer() {
+ return buffer;
+ }
+
+ @Override
+ public boolean hasArray() {
+ return buffer.hasArray();
+ }
+
+ @Override
+ public byte[] array() {
+ return buffer.array();
+ }
+
+ @Override
+ public int arrayOffset() {
+ return buffer.arrayOffset();
+ }
+
+ @Override
+ public int position() {
+ return buffer.position();
+ }
+
+ @Override
+ public AllocatedBuffer position(int position) {
+ buffer.position(position);
+ return this;
+ }
+
+ @Override
+ public int limit() {
+ return buffer.limit();
+ }
+
+ @Override
+ public int remaining() {
+ return buffer.remaining();
+ }
+ };
+ }
+
+ private static AllocatedBuffer wrapNoCheck(
+ final byte[] bytes, final int offset, final int length) {
+ return new AllocatedBuffer() {
+ // Relative to offset.
+ private int position;
+
+ @Override
+ public boolean hasNioBuffer() {
+ return false;
+ }
+
+ @Override
+ public ByteBuffer nioBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasArray() {
+ return true;
+ }
+
+ @Override
+ public byte[] array() {
+ return bytes;
+ }
+
+ @Override
+ public int arrayOffset() {
+ return offset;
+ }
+
+ @Override
+ public int position() {
+ return position;
+ }
+
+ @Override
+ public AllocatedBuffer position(int position) {
+ if (position < 0 || position > length) {
+ throw new IllegalArgumentException("Invalid position: " + position);
+ }
+ this.position = position;
+ return this;
+ }
+
+ @Override
+ public int limit() {
+ // Relative to offset.
+ return length;
+ }
+
+ @Override
+ public int remaining() {
+ return length - position;
+ }
+ };
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
new file mode 100755
index 000000000..a969c04c5
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
@@ -0,0 +1,1076 @@
+// 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.MessageSchema.getMutableUnknownFields;
+
+import com.google.protobuf.Internal.ProtobufList;
+import java.io.IOException;
+
+/**
+ * Helper functions to decode protobuf wire format from a byte array.
+ *
+ * <p>Note that these functions don't do boundary check on the byte array but instead rely on Java
+ * VM to check it. That means parsing rountines utilizing these functions must catch
+ * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when
+ * crossing protobuf public API boundaries.
+ */
+final class ArrayDecoders {
+ /**
+ * A helper used to return multiple values in a Java function. Java doesn't natively support
+ * returning multiple values in a function. Creating a new Object to hold the return values will
+ * be too expensive. Instead, we pass a Registers instance to functions that want to return
+ * multiple values and let the function set the return value in this Registers instance instead.
+ *
+ * <p>TODO(xiaofeng): This could be merged into CodedInputStream or CodedInputStreamReader which
+ * is already being passed through all the parsing rountines.
+ */
+ static final class Registers {
+ public int int1;
+ public long long1;
+ public Object object1;
+ public final ExtensionRegistryLite extensionRegistry;
+
+ Registers() {
+ this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry();
+ }
+
+ Registers(ExtensionRegistryLite extensionRegistry) {
+ if (extensionRegistry == null) {
+ throw new NullPointerException();
+ }
+ this.extensionRegistry = extensionRegistry;
+ }
+ }
+
+ /**
+ * Decodes a varint. Returns the position after the varint. The decoded varint is stored in
+ * registers.int1.
+ */
+ static int decodeVarint32(byte[] data, int position, Registers registers) {
+ int value = data[position++];
+ if (value >= 0) {
+ registers.int1 = value;
+ return position;
+ }
+ return decodeVarint32(value, data, position, registers);
+ }
+
+ /** Like decodeVarint32 except that the first byte is already read. */
+ static int decodeVarint32(int firstByte, byte[] data, int position, Registers registers) {
+ int value = firstByte & 0x7F;
+ final byte b2 = data[position++];
+ if (b2 >= 0) {
+ registers.int1 = value | ((int) b2 << 7);
+ return position;
+ }
+ value |= (b2 & 0x7F) << 7;
+
+ final byte b3 = data[position++];
+ if (b3 >= 0) {
+ registers.int1 = value | ((int) b3 << 14);
+ return position;
+ }
+ value |= (b3 & 0x7F) << 14;
+
+ final byte b4 = data[position++];
+ if (b4 >= 0) {
+ registers.int1 = value | ((int) b4 << 21);
+ return position;
+ }
+ value |= (b4 & 0x7F) << 21;
+
+ final byte b5 = data[position++];
+ if (b5 >= 0) {
+ registers.int1 = value | ((int) b5 << 28);
+ return position;
+ }
+ value |= (b5 & 0x7F) << 28;
+
+ while (data[position++] < 0) {}
+
+ registers.int1 = value;
+ return position;
+ }
+
+ /**
+ * Decodes a varint. Returns the position after the varint. The decoded varint is stored in
+ * registers.long1.
+ */
+ static int decodeVarint64(byte[] data, int position, Registers registers) {
+ long value = data[position++];
+ if (value >= 0) {
+ registers.long1 = value;
+ return position;
+ } else {
+ return decodeVarint64(value, data, position, registers);
+ }
+ }
+
+ /** Like decodeVarint64 except that the first byte is already read. */
+ static int decodeVarint64(long firstByte, byte[] data, int position, Registers registers) {
+ long value = firstByte & 0x7F;
+ byte next = data[position++];
+ int shift = 7;
+ value |= (long) (next & 0x7F) << 7;
+ while (next < 0) {
+ next = data[position++];
+ shift += 7;
+ value |= (long) (next & 0x7F) << shift;
+ }
+ registers.long1 = value;
+ return position;
+ }
+
+ /** Decodes and returns a fixed32 value. */
+ static int decodeFixed32(byte[] data, int position) {
+ return (data[position] & 0xff)
+ | ((data[position + 1] & 0xff) << 8)
+ | ((data[position + 2] & 0xff) << 16)
+ | ((data[position + 3] & 0xff) << 24);
+ }
+
+ /** Decodes and returns a fixed64 value. */
+ static long decodeFixed64(byte[] data, int position) {
+ return (data[position] & 0xffL)
+ | ((data[position + 1] & 0xffL) << 8)
+ | ((data[position + 2] & 0xffL) << 16)
+ | ((data[position + 3] & 0xffL) << 24)
+ | ((data[position + 4] & 0xffL) << 32)
+ | ((data[position + 5] & 0xffL) << 40)
+ | ((data[position + 6] & 0xffL) << 48)
+ | ((data[position + 7] & 0xffL) << 56);
+ }
+
+ /** Decodes and returns a double value. */
+ static double decodeDouble(byte[] data, int position) {
+ return Double.longBitsToDouble(decodeFixed64(data, position));
+ }
+
+ /** Decodes and returns a float value. */
+ static float decodeFloat(byte[] data, int position) {
+ return Float.intBitsToFloat(decodeFixed32(data, position));
+ }
+
+ /** Decodes a string value. */
+ static int decodeString(byte[] data, int position, Registers registers)
+ throws InvalidProtocolBufferException {
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length == 0) {
+ registers.object1 = "";
+ return position;
+ } else {
+ registers.object1 = new String(data, position, length, Internal.UTF_8);
+ return position + length;
+ }
+ }
+
+ /** Decodes a string value with utf8 check. */
+ static int decodeStringRequireUtf8(byte[] data, int position, Registers registers)
+ throws InvalidProtocolBufferException {
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length == 0) {
+ registers.object1 = "";
+ return position;
+ } else {
+ registers.object1 = Utf8.decodeUtf8(data, position, length);
+ return position + length;
+ }
+ }
+
+ /** Decodes a bytes value. */
+ static int decodeBytes(byte[] data, int position, Registers registers)
+ throws InvalidProtocolBufferException {
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length > data.length - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } else if (length == 0) {
+ registers.object1 = ByteString.EMPTY;
+ return position;
+ } else {
+ registers.object1 = ByteString.copyFrom(data, position, length);
+ return position + length;
+ }
+ }
+
+ /** Decodes a message value. */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ static int decodeMessageField(
+ Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException {
+ int length = data[position++];
+ if (length < 0) {
+ position = decodeVarint32(length, data, position, registers);
+ length = registers.int1;
+ }
+ if (length < 0 || length > limit - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ Object result = schema.newInstance();
+ schema.mergeFrom(result, data, position, position + length, registers);
+ schema.makeImmutable(result);
+ registers.object1 = result;
+ return position + length;
+ }
+
+ /** Decodes a group value. */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ static int decodeGroupField(
+ Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)
+ throws IOException {
+ // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema
+ // and it can't be used in group fields).
+ final MessageSchema messageSchema = (MessageSchema) schema;
+ Object result = messageSchema.newInstance();
+ // It's OK to directly use parseProto2Message since proto3 doesn't have group.
+ final int endPosition =
+ messageSchema.parseProto2Message(result, data, position, limit, endGroup, registers);
+ messageSchema.makeImmutable(result);
+ registers.object1 = result;
+ return endPosition;
+ }
+
+ /** Decodes a repeated 32-bit varint field. Returns the position after all read values. */
+ static int decodeVarint32List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final IntArrayList output = (IntArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ output.addInt(registers.int1);
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint32(data, nextPosition, registers);
+ output.addInt(registers.int1);
+ }
+ return position;
+ }
+
+ /** Decodes a repeated 64-bit varint field. Returns the position after all read values. */
+ static int decodeVarint64List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final LongArrayList output = (LongArrayList) list;
+ position = decodeVarint64(data, position, registers);
+ output.addLong(registers.long1);
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint64(data, nextPosition, registers);
+ output.addLong(registers.long1);
+ }
+ return position;
+ }
+
+ /** Decodes a repeated fixed32 field. Returns the position after all read values. */
+ static int decodeFixed32List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final IntArrayList output = (IntArrayList) list;
+ output.addInt(decodeFixed32(data, position));
+ position += 4;
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ output.addInt(decodeFixed32(data, nextPosition));
+ position = nextPosition + 4;
+ }
+ return position;
+ }
+
+ /** Decodes a repeated fixed64 field. Returns the position after all read values. */
+ static int decodeFixed64List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final LongArrayList output = (LongArrayList) list;
+ output.addLong(decodeFixed64(data, position));
+ position += 8;
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ output.addLong(decodeFixed64(data, nextPosition));
+ position = nextPosition + 8;
+ }
+ return position;
+ }
+
+ /** Decodes a repeated float field. Returns the position after all read values. */
+ static int decodeFloatList(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final FloatArrayList output = (FloatArrayList) list;
+ output.addFloat(decodeFloat(data, position));
+ position += 4;
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ output.addFloat(decodeFloat(data, nextPosition));
+ position = nextPosition + 4;
+ }
+ return position;
+ }
+
+ /** Decodes a repeated double field. Returns the position after all read values. */
+ static int decodeDoubleList(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final DoubleArrayList output = (DoubleArrayList) list;
+ output.addDouble(decodeDouble(data, position));
+ position += 8;
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ output.addDouble(decodeDouble(data, nextPosition));
+ position = nextPosition + 8;
+ }
+ return position;
+ }
+
+ /** Decodes a repeated boolean field. Returns the position after all read values. */
+ static int decodeBoolList(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final BooleanArrayList output = (BooleanArrayList) list;
+ position = decodeVarint64(data, position, registers);
+ output.addBoolean(registers.long1 != 0);
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint64(data, nextPosition, registers);
+ output.addBoolean(registers.long1 != 0);
+ }
+ return position;
+ }
+
+ /** Decodes a repeated sint32 field. Returns the position after all read values. */
+ static int decodeSInt32List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final IntArrayList output = (IntArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint32(data, nextPosition, registers);
+ output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
+ }
+ return position;
+ }
+
+ /** Decodes a repeated sint64 field. Returns the position after all read values. */
+ static int decodeSInt64List(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) {
+ final LongArrayList output = (LongArrayList) list;
+ position = decodeVarint64(data, position, registers);
+ output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint64(data, nextPosition, registers);
+ output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
+ }
+ return position;
+ }
+
+ /** Decodes a packed 32-bit varint field. Returns the position after all read values. */
+ static int decodePackedVarint32List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final IntArrayList output = (IntArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ position = decodeVarint32(data, position, registers);
+ output.addInt(registers.int1);
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed 64-bit varint field. Returns the position after all read values. */
+ static int decodePackedVarint64List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final LongArrayList output = (LongArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ position = decodeVarint64(data, position, registers);
+ output.addLong(registers.long1);
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed fixed32 field. Returns the position after all read values. */
+ static int decodePackedFixed32List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final IntArrayList output = (IntArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ output.addInt(decodeFixed32(data, position));
+ position += 4;
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed fixed64 field. Returns the position after all read values. */
+ static int decodePackedFixed64List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final LongArrayList output = (LongArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ output.addLong(decodeFixed64(data, position));
+ position += 8;
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed float field. Returns the position after all read values. */
+ static int decodePackedFloatList(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final FloatArrayList output = (FloatArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ output.addFloat(decodeFloat(data, position));
+ position += 4;
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed double field. Returns the position after all read values. */
+ static int decodePackedDoubleList(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final DoubleArrayList output = (DoubleArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ output.addDouble(decodeDouble(data, position));
+ position += 8;
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed boolean field. Returns the position after all read values. */
+ static int decodePackedBoolList(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final BooleanArrayList output = (BooleanArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ position = decodeVarint64(data, position, registers);
+ output.addBoolean(registers.long1 != 0);
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed sint32 field. Returns the position after all read values. */
+ static int decodePackedSInt32List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final IntArrayList output = (IntArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ position = decodeVarint32(data, position, registers);
+ output.addInt(CodedInputStream.decodeZigZag32(registers.int1));
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a packed sint64 field. Returns the position after all read values. */
+ @SuppressWarnings("unchecked")
+ static int decodePackedSInt64List(
+ byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException {
+ final LongArrayList output = (LongArrayList) list;
+ position = decodeVarint32(data, position, registers);
+ final int fieldLimit = position + registers.int1;
+ while (position < fieldLimit) {
+ position = decodeVarint64(data, position, registers);
+ output.addLong(CodedInputStream.decodeZigZag64(registers.long1));
+ }
+ if (position != fieldLimit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return position;
+ }
+
+ /** Decodes a repeated string field. Returns the position after all read values. */
+ @SuppressWarnings("unchecked")
+ static int decodeStringList(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
+ throws InvalidProtocolBufferException {
+ final ProtobufList<String> output = (ProtobufList<String>) list;
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length == 0) {
+ output.add("");
+ } else {
+ String value = new String(data, position, length, Internal.UTF_8);
+ output.add(value);
+ position += length;
+ }
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint32(data, nextPosition, registers);
+ final int nextLength = registers.int1;
+ if (nextLength < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (nextLength == 0) {
+ output.add("");
+ } else {
+ String value = new String(data, position, nextLength, Internal.UTF_8);
+ output.add(value);
+ position += nextLength;
+ }
+ }
+ return position;
+ }
+
+ /**
+ * Decodes a repeated string field with utf8 check. Returns the position after all read values.
+ */
+ @SuppressWarnings("unchecked")
+ static int decodeStringListRequireUtf8(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
+ throws InvalidProtocolBufferException {
+ final ProtobufList<String> output = (ProtobufList<String>) list;
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length == 0) {
+ output.add("");
+ } else {
+ if (!Utf8.isValidUtf8(data, position, position + length)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ String value = new String(data, position, length, Internal.UTF_8);
+ output.add(value);
+ position += length;
+ }
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint32(data, nextPosition, registers);
+ final int nextLength = registers.int1;
+ if (nextLength < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (nextLength == 0) {
+ output.add("");
+ } else {
+ if (!Utf8.isValidUtf8(data, position, position + nextLength)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ String value = new String(data, position, nextLength, Internal.UTF_8);
+ output.add(value);
+ position += nextLength;
+ }
+ }
+ return position;
+ }
+
+ /** Decodes a repeated bytes field. Returns the position after all read values. */
+ @SuppressWarnings("unchecked")
+ static int decodeBytesList(
+ int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)
+ throws InvalidProtocolBufferException {
+ final ProtobufList<ByteString> output = (ProtobufList<ByteString>) list;
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length > data.length - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } else if (length == 0) {
+ output.add(ByteString.EMPTY);
+ } else {
+ output.add(ByteString.copyFrom(data, position, length));
+ position += length;
+ }
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeVarint32(data, nextPosition, registers);
+ final int nextLength = registers.int1;
+ if (nextLength < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (nextLength > data.length - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } else if (nextLength == 0) {
+ output.add(ByteString.EMPTY);
+ } else {
+ output.add(ByteString.copyFrom(data, position, nextLength));
+ position += nextLength;
+ }
+ }
+ return position;
+ }
+
+ /**
+ * Decodes a repeated message field
+ *
+ * @return The position of after read all messages
+ */
+ @SuppressWarnings({"unchecked"})
+ static int decodeMessageList(
+ Schema<?> schema,
+ int tag,
+ byte[] data,
+ int position,
+ int limit,
+ ProtobufList<?> list,
+ Registers registers)
+ throws IOException {
+ final ProtobufList<Object> output = (ProtobufList<Object>) list;
+ position = decodeMessageField(schema, data, position, limit, registers);
+ output.add(registers.object1);
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeMessageField(schema, data, nextPosition, limit, registers);
+ output.add(registers.object1);
+ }
+ return position;
+ }
+
+ /**
+ * Decodes a repeated group field
+ *
+ * @return The position of after read all groups
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ static int decodeGroupList(
+ Schema schema,
+ int tag,
+ byte[] data,
+ int position,
+ int limit,
+ ProtobufList<?> list,
+ Registers registers)
+ throws IOException {
+ final ProtobufList<Object> output = (ProtobufList<Object>) list;
+ final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
+ position = decodeGroupField(schema, data, position, limit, endgroup, registers);
+ output.add(registers.object1);
+ while (position < limit) {
+ int nextPosition = decodeVarint32(data, position, registers);
+ if (tag != registers.int1) {
+ break;
+ }
+ position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers);
+ output.add(registers.object1);
+ }
+ return position;
+ }
+
+ static int decodeExtensionOrUnknownField(
+ int tag, byte[] data, int position, int limit,
+ Object message,
+ MessageLite defaultInstance,
+ UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
+ Registers registers)
+ throws IOException {
+ final int number = tag >>> 3;
+ GeneratedMessageLite.GeneratedExtension extension =
+ registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number);
+ if (extension == null) {
+ return decodeUnknownField(
+ tag, data, position, limit, getMutableUnknownFields(message), registers);
+ } else {
+ ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable();
+ return decodeExtension(
+ tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message,
+ extension, unknownFieldSchema, registers);
+ }
+ }
+
+ static int decodeExtension(
+ int tag,
+ byte[] data,
+ int position,
+ int limit,
+ GeneratedMessageLite.ExtendableMessage<?, ?> message,
+ GeneratedMessageLite.GeneratedExtension<?, ?> extension,
+ UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema,
+ Registers registers)
+ throws IOException {
+ final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions = message.extensions;
+ final int fieldNumber = tag >>> 3;
+ if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
+ switch (extension.getLiteType()) {
+ case DOUBLE:
+ {
+ DoubleArrayList list = new DoubleArrayList();
+ position = decodePackedDoubleList(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case FLOAT:
+ {
+ FloatArrayList list = new FloatArrayList();
+ position = decodePackedFloatList(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case INT64:
+ case UINT64:
+ {
+ LongArrayList list = new LongArrayList();
+ position = decodePackedVarint64List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case INT32:
+ case UINT32:
+ {
+ IntArrayList list = new IntArrayList();
+ position = decodePackedVarint32List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case FIXED64:
+ case SFIXED64:
+ {
+ LongArrayList list = new LongArrayList();
+ position = decodePackedFixed64List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case FIXED32:
+ case SFIXED32:
+ {
+ IntArrayList list = new IntArrayList();
+ position = decodePackedFixed32List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case BOOL:
+ {
+ BooleanArrayList list = new BooleanArrayList();
+ position = decodePackedBoolList(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case SINT32:
+ {
+ IntArrayList list = new IntArrayList();
+ position = decodePackedSInt32List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case SINT64:
+ {
+ LongArrayList list = new LongArrayList();
+ position = decodePackedSInt64List(data, position, list, registers);
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ case ENUM:
+ {
+ IntArrayList list = new IntArrayList();
+ position = decodePackedVarint32List(data, position, list, registers);
+ UnknownFieldSetLite unknownFields = message.unknownFields;
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = null;
+ }
+ unknownFields =
+ SchemaUtil.filterUnknownEnumList(
+ fieldNumber,
+ list,
+ extension.descriptor.getEnumType(),
+ unknownFields,
+ unknownFieldSchema);
+ if (unknownFields != null) {
+ message.unknownFields = unknownFields;
+ }
+ extensions.setField(extension.descriptor, list);
+ break;
+ }
+ default:
+ throw new IllegalStateException(
+ "Type cannot be packed: " + extension.descriptor.getLiteType());
+ }
+ } else {
+ Object value = null;
+ // Enum is a special case becasue unknown enum values will be put into UnknownFieldSetLite.
+ if (extension.getLiteType() == WireFormat.FieldType.ENUM) {
+ position = decodeVarint32(data, position, registers);
+ Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1);
+ if (enumValue == null) {
+ UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ ((GeneratedMessageLite) message).unknownFields = unknownFields;
+ }
+ SchemaUtil.storeUnknownEnum(
+ fieldNumber, registers.int1, unknownFields, unknownFieldSchema);
+ return position;
+ }
+ // Note, we store the integer value instead of the actual enum object in FieldSet.
+ // This is also different from full-runtime where we store EnumValueDescriptor.
+ value = registers.int1;
+ } else {
+ switch (extension.getLiteType()) {
+ case DOUBLE:
+ value = decodeDouble(data, position);
+ position += 8;
+ break;
+ case FLOAT:
+ value = decodeFloat(data, position);
+ position += 4;
+ break;
+ case INT64:
+ case UINT64:
+ position = decodeVarint64(data, position, registers);
+ value = registers.long1;
+ break;
+ case INT32:
+ case UINT32:
+ position = decodeVarint32(data, position, registers);
+ value = registers.int1;
+ break;
+ case FIXED64:
+ case SFIXED64:
+ value = decodeFixed64(data, position);
+ position += 8;
+ break;
+ case FIXED32:
+ case SFIXED32:
+ value = decodeFixed32(data, position);
+ position += 4;
+ break;
+ case BOOL:
+ position = decodeVarint64(data, position, registers);
+ value = (registers.long1 != 0);
+ break;
+ case BYTES:
+ position = decodeBytes(data, position, registers);
+ value = registers.object1;
+ break;
+ case SINT32:
+ position = decodeVarint32(data, position, registers);
+ value = CodedInputStream.decodeZigZag32(registers.int1);
+ break;
+ case SINT64:
+ position = decodeVarint64(data, position, registers);
+ value = CodedInputStream.decodeZigZag64(registers.long1);
+ break;
+ case STRING:
+ position = decodeString(data, position, registers);
+ value = registers.object1;
+ break;
+ case GROUP:
+ final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP;
+ position = decodeGroupField(
+ Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()),
+ data, position, limit, endTag, registers);
+ value = registers.object1;
+ break;
+
+ case MESSAGE:
+ position = decodeMessageField(
+ Protobuf.getInstance().schemaFor(extension.getMessageDefaultInstance().getClass()),
+ data, position, limit, registers);
+ value = registers.object1;
+ break;
+
+ case ENUM:
+ throw new IllegalStateException("Shouldn't reach here.");
+ }
+ }
+ if (extension.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor, value);
+ } else {
+ switch (extension.getLiteType()) {
+ case MESSAGE:
+ case GROUP:
+ Object oldValue = extensions.getField(extension.descriptor);
+ if (oldValue != null) {
+ value = Internal.mergeMessage(oldValue, value);
+ }
+ break;
+ default:
+ break;
+ }
+ extensions.setField(extension.descriptor, value);
+ }
+ }
+ return position;
+ }
+
+ /** Decodes an unknown field. */
+ static int decodeUnknownField(
+ int tag,
+ byte[] data,
+ int position,
+ int limit,
+ UnknownFieldSetLite unknownFields,
+ Registers registers)
+ throws InvalidProtocolBufferException {
+ if (WireFormat.getTagFieldNumber(tag) == 0) {
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ position = decodeVarint64(data, position, registers);
+ unknownFields.storeField(tag, registers.long1);
+ return position;
+ case WireFormat.WIRETYPE_FIXED32:
+ unknownFields.storeField(tag, decodeFixed32(data, position));
+ return position + 4;
+ case WireFormat.WIRETYPE_FIXED64:
+ unknownFields.storeField(tag, decodeFixed64(data, position));
+ return position + 8;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0) {
+ throw InvalidProtocolBufferException.negativeSize();
+ } else if (length > data.length - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } else if (length == 0) {
+ unknownFields.storeField(tag, ByteString.EMPTY);
+ } else {
+ unknownFields.storeField(tag, ByteString.copyFrom(data, position, length));
+ }
+ return position + length;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance();
+ final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
+ int lastTag = 0;
+ while (position < limit) {
+ position = decodeVarint32(data, position, registers);
+ lastTag = registers.int1;
+ if (lastTag == endGroup) {
+ break;
+ }
+ position = decodeUnknownField(lastTag, data, position, limit, child, registers);
+ }
+ if (position > limit || lastTag != endGroup) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ unknownFields.storeField(tag, child);
+ return position;
+ default:
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ }
+
+ /** Skips an unknown field. */
+ static int skipField(int tag, byte[] data, int position, int limit, Registers registers)
+ throws InvalidProtocolBufferException {
+ if (WireFormat.getTagFieldNumber(tag) == 0) {
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ position = decodeVarint64(data, position, registers);
+ return position;
+ case WireFormat.WIRETYPE_FIXED32:
+ return position + 4;
+ case WireFormat.WIRETYPE_FIXED64:
+ return position + 8;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ position = decodeVarint32(data, position, registers);
+ return position + registers.int1;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
+ int lastTag = 0;
+ while (position < limit) {
+ position = decodeVarint32(data, position, registers);
+ lastTag = registers.int1;
+ if (lastTag == endGroup) {
+ break;
+ }
+ position = skipField(lastTag, data, position, limit, registers);
+ }
+ if (position > limit || lastTag != endGroup) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ return position;
+ default:
+ throw InvalidProtocolBufferException.invalidTag();
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/BinaryReader.java b/java/core/src/main/java/com/google/protobuf/BinaryReader.java
new file mode 100755
index 000000000..d64574c2a
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/BinaryReader.java
@@ -0,0 +1,1729 @@
+// 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.FIXED32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED64_SIZE;
+import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
+import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
+import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A {@link Reader} that reads from a buffer containing a message serialized with the binary
+ * protocol.
+ */
+@ExperimentalApi
+abstract class BinaryReader implements Reader {
+ private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
+ private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
+
+ /**
+ * Creates a new reader using the given {@code buffer} as input.
+ *
+ * @param buffer the input buffer. The buffer (including position, limit, etc.) will not be
+ * modified. To increment the buffer position after the read completes, use the value returned
+ * by {@link #getTotalBytesRead()}.
+ * @param bufferIsImmutable if {@code true} the reader assumes that the content of {@code buffer}
+ * will never change and any allocated {@link ByteString} instances will by directly wrap
+ * slices of {@code buffer}.
+ * @return the reader
+ */
+ public static BinaryReader newInstance(ByteBuffer buffer, boolean bufferIsImmutable) {
+ if (buffer.hasArray()) {
+ // TODO(nathanmittler): Add support for unsafe operations.
+ return new SafeHeapReader(buffer, bufferIsImmutable);
+ }
+ // TODO(nathanmittler): Add support for direct buffers
+ throw new IllegalArgumentException("Direct buffers not yet supported");
+ }
+
+ /** Only allow subclassing for inner classes. */
+ private BinaryReader() {}
+
+ /** Returns the total number of bytes read so far from the input buffer. */
+ public abstract int getTotalBytesRead();
+
+ @Override
+ public boolean shouldDiscardUnknownFields() {
+ return false;
+ }
+
+ /**
+ * A {@link BinaryReader} implementation that operates on a heap {@link ByteBuffer}. Uses only
+ * safe operations on the underlying array.
+ */
+ private static final class SafeHeapReader extends BinaryReader {
+ private final boolean bufferIsImmutable;
+ private final byte[] buffer;
+ private int pos;
+ private final int initialPos;
+ private int limit;
+ private int tag;
+ private int endGroupTag;
+
+ public SafeHeapReader(ByteBuffer bytebuf, boolean bufferIsImmutable) {
+ this.bufferIsImmutable = bufferIsImmutable;
+ buffer = bytebuf.array();
+ initialPos = pos = bytebuf.arrayOffset() + bytebuf.position();
+ limit = bytebuf.arrayOffset() + bytebuf.limit();
+ }
+
+ private boolean isAtEnd() {
+ return pos == limit;
+ }
+
+ @Override
+ public int getTotalBytesRead() {
+ return pos - initialPos;
+ }
+
+ @Override
+ public int getFieldNumber() throws IOException {
+ if (isAtEnd()) {
+ return Reader.READ_DONE;
+ }
+ tag = readVarint32();
+ if (tag == endGroupTag) {
+ return Reader.READ_DONE;
+ }
+ return WireFormat.getTagFieldNumber(tag);
+ }
+
+ @Override
+ public int getTag() {
+ return tag;
+ }
+
+ @Override
+ public boolean skipField() throws IOException {
+ if (isAtEnd() || tag == endGroupTag) {
+ return false;
+ }
+
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_VARINT:
+ skipVarint();
+ return true;
+ case WIRETYPE_FIXED64:
+ skipBytes(FIXED64_SIZE);
+ return true;
+ case WIRETYPE_LENGTH_DELIMITED:
+ skipBytes(readVarint32());
+ return true;
+ case WIRETYPE_FIXED32:
+ skipBytes(FIXED32_SIZE);
+ return true;
+ case WIRETYPE_START_GROUP:
+ skipGroup();
+ return true;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return Double.longBitsToDouble(readLittleEndian64());
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return Float.intBitsToFloat(readLittleEndian32());
+ }
+
+ @Override
+ public long readUInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint64();
+ }
+
+ @Override
+ public long readInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint64();
+ }
+
+ @Override
+ public int readInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint32();
+ }
+
+ @Override
+ public long readFixed64() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return readLittleEndian64();
+ }
+
+ @Override
+ public int readFixed32() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return readLittleEndian32();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint32() != 0;
+ }
+
+ @Override
+ public String readString() throws IOException {
+ return readStringInternal(false);
+ }
+
+ @Override
+ public String readStringRequireUtf8() throws IOException {
+ return readStringInternal(true);
+ }
+
+ public String readStringInternal(boolean requireUtf8) throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ final int size = readVarint32();
+ if (size == 0) {
+ return "";
+ }
+
+ requireBytes(size);
+ if (requireUtf8 && !Utf8.isValidUtf8(buffer, pos, pos + size)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ String result = new String(buffer, pos, size, Internal.UTF_8);
+ pos += size;
+ return result;
+ }
+
+ @Override
+ public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
+ }
+
+ @Override
+ public <T> T readMessageBySchemaWithCheck(
+ Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return readMessage(schema, extensionRegistry);
+ }
+
+ private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int size = readVarint32();
+ requireBytes(size);
+
+ // Update the limit.
+ int prevLimit = limit;
+ int newLimit = pos + size;
+ limit = newLimit;
+
+ try {
+ // Allocate and read the message.
+ T message = schema.newInstance();
+ schema.mergeFrom(message, this, extensionRegistry);
+ schema.makeImmutable(message);
+
+ if (pos != newLimit) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ return message;
+ } finally {
+ // Restore the limit.
+ limit = prevLimit;
+ }
+ }
+
+ @Override
+ public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_START_GROUP);
+ return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
+ }
+
+ @Override
+ public <T> T readGroupBySchemaWithCheck(
+ Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
+ requireWireType(WIRETYPE_START_GROUP);
+ return readGroup(schema, extensionRegistry);
+ }
+
+ private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int prevEndGroupTag = endGroupTag;
+ endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
+
+ try {
+ // Allocate and read the message.
+ T message = schema.newInstance();
+ schema.mergeFrom(message, this, extensionRegistry);
+ schema.makeImmutable(message);
+
+ if (tag != endGroupTag) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ return message;
+ } finally {
+ // Restore the old end group tag.
+ endGroupTag = prevEndGroupTag;
+ }
+ }
+
+ @Override
+ public ByteString readBytes() throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ int size = readVarint32();
+ if (size == 0) {
+ return ByteString.EMPTY;
+ }
+
+ requireBytes(size);
+ ByteString bytes =
+ bufferIsImmutable
+ ? ByteString.wrap(buffer, pos, size)
+ : ByteString.copyFrom(buffer, pos, size);
+ pos += size;
+ return bytes;
+ }
+
+ @Override
+ public int readUInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint32();
+ }
+
+ @Override
+ public int readEnum() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return readVarint32();
+ }
+
+ @Override
+ public int readSFixed32() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return readLittleEndian32();
+ }
+
+ @Override
+ public long readSFixed64() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return readLittleEndian64();
+ }
+
+ @Override
+ public int readSInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return CodedInputStream.decodeZigZag32(readVarint32());
+ }
+
+ @Override
+ public long readSInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return CodedInputStream.decodeZigZag64(readVarint64());
+ }
+
+ @Override
+ public void readDoubleList(List<Double> target) throws IOException {
+ if (target instanceof DoubleArrayList) {
+ DoubleArrayList plist = (DoubleArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addDouble(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addDouble(readDouble());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(Double.longBitsToDouble(readLittleEndian64_NoCheck()));
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(readDouble());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFloatList(List<Float> target) throws IOException {
+ if (target instanceof FloatArrayList) {
+ FloatArrayList plist = (FloatArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addFloat(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addFloat(readFloat());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(Float.intBitsToFloat(readLittleEndian32_NoCheck()));
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(readFloat());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readUInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addLong(readVarint64());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(readUInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint64());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readUInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addLong(readVarint64());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(readInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint64());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(readVarint32());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(readInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint32());
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFixed64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addLong(readLittleEndian64_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addLong(readFixed64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readLittleEndian64_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(readFixed64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFixed32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(readLittleEndian32_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addInt(readFixed32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readLittleEndian32_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(readFixed32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readBoolList(List<Boolean> target) throws IOException {
+ if (target instanceof BooleanArrayList) {
+ BooleanArrayList plist = (BooleanArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addBoolean(readVarint32() != 0);
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addBoolean(readBool());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint32() != 0);
+ }
+ requirePosition(fieldEndPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readBool());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readStringList(List<String> target) throws IOException {
+ readStringListInternal(target, false);
+ }
+
+ @Override
+ public void readStringListRequireUtf8(List<String> target) throws IOException {
+ readStringListInternal(target, true);
+ }
+
+ public void readStringListInternal(List<String> target, boolean requireUtf8)
+ throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+
+ if (target instanceof LazyStringList && !requireUtf8) {
+ LazyStringList lazyList = (LazyStringList) target;
+ while (true) {
+ lazyList.add(readBytes());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ } else {
+ while (true) {
+ target.add(readStringInternal(requireUtf8));
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public <T> void readMessageList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
+ readMessageList(target, schema, extensionRegistry);
+ }
+
+ @Override
+ public <T> void readMessageList(
+ List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ final int listTag = tag;
+ while (true) {
+ target.add(readMessage(schema, extensionRegistry));
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != listTag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public <T> void readGroupList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
+ readGroupList(target, schema, extensionRegistry);
+ }
+
+ @Override
+ public <T> void readGroupList(
+ List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ final int listTag = tag;
+ while (true) {
+ target.add(readGroup(schema, extensionRegistry));
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != listTag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void readBytesList(List<ByteString> target) throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+
+ while (true) {
+ target.add(readBytes());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void readUInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(readVarint32());
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(readUInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint32());
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readUInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readEnumList(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(readVarint32());
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(readEnum());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readVarint32());
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readEnum());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSFixed32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(readLittleEndian32_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addInt(readSFixed32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed32Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readLittleEndian32_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(readSFixed32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSFixed64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addLong(readLittleEndian64_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addLong(readSFixed64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ verifyPackedFixed64Length(bytes);
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(readLittleEndian64_NoCheck());
+ }
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(readSFixed64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addInt(CodedInputStream.decodeZigZag32(readVarint32()));
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(readSInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(CodedInputStream.decodeZigZag32(readVarint32()));
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readSInt32());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ plist.addLong(CodedInputStream.decodeZigZag64(readVarint64()));
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(readSInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = readVarint32();
+ final int fieldEndPos = pos + bytes;
+ while (pos < fieldEndPos) {
+ target.add(CodedInputStream.decodeZigZag64(readVarint64()));
+ }
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(readSInt64());
+
+ if (isAtEnd()) {
+ return;
+ }
+ int prevPos = pos;
+ int nextTag = readVarint32();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Rewind the buffer position to before
+ // the new tag.
+ pos = prevPos;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <K, V> void readMap(
+ Map<K, V> target,
+ MapEntryLite.Metadata<K, V> metadata,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ int size = readVarint32();
+ requireBytes(size);
+
+ // Update the limit.
+ int prevLimit = limit;
+ int newLimit = pos + size;
+ limit = newLimit;
+
+ try {
+ K key = metadata.defaultKey;
+ V value = metadata.defaultValue;
+ while (true) {
+ int number = getFieldNumber();
+ if (number == READ_DONE) {
+ break;
+ }
+ try {
+ switch (number) {
+ case 1:
+ key = (K) readField(metadata.keyType, null, null);
+ break;
+ case 2:
+ value =
+ (V)
+ readField(
+ metadata.valueType,
+ metadata.defaultValue.getClass(),
+ extensionRegistry);
+ break;
+ default:
+ if (!skipField()) {
+ throw new InvalidProtocolBufferException("Unable to parse map entry.");
+ }
+ break;
+ }
+ } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) {
+ // the type doesn't match, skip the field.
+ if (!skipField()) {
+ throw new InvalidProtocolBufferException("Unable to parse map entry.");
+ }
+ }
+ }
+ target.put(key, value);
+ } finally {
+ // Restore the limit.
+ limit = prevLimit;
+ }
+ }
+
+ private Object readField(
+ WireFormat.FieldType fieldType,
+ Class<?> messageType,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ switch (fieldType) {
+ case BOOL:
+ return readBool();
+ case BYTES:
+ return readBytes();
+ case DOUBLE:
+ return readDouble();
+ case ENUM:
+ return readEnum();
+ case FIXED32:
+ return readFixed32();
+ case FIXED64:
+ return readFixed64();
+ case FLOAT:
+ return readFloat();
+ case INT32:
+ return readInt32();
+ case INT64:
+ return readInt64();
+ case MESSAGE:
+ return readMessage(messageType, extensionRegistry);
+ case SFIXED32:
+ return readSFixed32();
+ case SFIXED64:
+ return readSFixed64();
+ case SINT32:
+ return readSInt32();
+ case SINT64:
+ return readSInt64();
+ case STRING:
+ return readStringRequireUtf8();
+ case UINT32:
+ return readUInt32();
+ case UINT64:
+ return readUInt64();
+ default:
+ throw new RuntimeException("unsupported field type.");
+ }
+ }
+
+ /** Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits. */
+ private int readVarint32() throws IOException {
+ // See implementation notes for readRawVarint64
+ int i = pos;
+
+ if (limit == pos) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ int x;
+ if ((x = buffer[i++]) >= 0) {
+ pos = i;
+ return x;
+ } else if (limit - i < 9) {
+ return (int) readVarint64SlowPath();
+ } else if ((x ^= (buffer[i++] << 7)) < 0) {
+ x ^= (~0 << 7);
+ } else if ((x ^= (buffer[i++] << 14)) >= 0) {
+ x ^= (~0 << 7) ^ (~0 << 14);
+ } else if ((x ^= (buffer[i++] << 21)) < 0) {
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21);
+ } else {
+ int y = buffer[i++];
+ x ^= y << 28;
+ x ^= (~0 << 7) ^ (~0 << 14) ^ (~0 << 21) ^ (~0 << 28);
+ if (y < 0
+ && buffer[i++] < 0
+ && buffer[i++] < 0
+ && buffer[i++] < 0
+ && buffer[i++] < 0
+ && buffer[i++] < 0) {
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+ }
+ pos = i;
+ return x;
+ }
+
+ public long readVarint64() 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.
+ int i = pos;
+
+ if (limit == i) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+
+ final byte[] buffer = this.buffer;
+ long x;
+ int y;
+ if ((y = buffer[i++]) >= 0) {
+ pos = i;
+ return y;
+ } else if (limit - i < 9) {
+ return readVarint64SlowPath();
+ } else if ((y ^= (buffer[i++] << 7)) < 0) {
+ x = y ^ (~0 << 7);
+ } else if ((y ^= (buffer[i++] << 14)) >= 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14));
+ } else if ((y ^= (buffer[i++] << 21)) < 0) {
+ x = y ^ ((~0 << 7) ^ (~0 << 14) ^ (~0 << 21));
+ } else if ((x = y ^ ((long) buffer[i++] << 28)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28);
+ } else if ((x ^= ((long) buffer[i++] << 35)) < 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35);
+ } else if ((x ^= ((long) buffer[i++] << 42)) >= 0L) {
+ x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42);
+ } else if ((x ^= ((long) buffer[i++] << 49)) < 0L) {
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49);
+ } else {
+ x ^= ((long) buffer[i++] << 56);
+ x ^=
+ (~0L << 7)
+ ^ (~0L << 14)
+ ^ (~0L << 21)
+ ^ (~0L << 28)
+ ^ (~0L << 35)
+ ^ (~0L << 42)
+ ^ (~0L << 49)
+ ^ (~0L << 56);
+ if (x < 0L) {
+ if (buffer[i++] < 0L) {
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+ }
+ }
+ pos = i;
+ return x;
+ }
+
+ private long readVarint64SlowPath() throws IOException {
+ long result = 0;
+ for (int shift = 0; shift < 64; shift += 7) {
+ final byte b = readByte();
+ result |= (long) (b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ private byte readByte() throws IOException {
+ if (pos == limit) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ return buffer[pos++];
+ }
+
+ private int readLittleEndian32() throws IOException {
+ requireBytes(FIXED32_SIZE);
+ return readLittleEndian32_NoCheck();
+ }
+
+ private long readLittleEndian64() throws IOException {
+ requireBytes(FIXED64_SIZE);
+ return readLittleEndian64_NoCheck();
+ }
+
+ private int readLittleEndian32_NoCheck() {
+ int p = pos;
+ final byte[] buffer = this.buffer;
+ pos = p + FIXED32_SIZE;
+ return (((buffer[p] & 0xff))
+ | ((buffer[p + 1] & 0xff) << 8)
+ | ((buffer[p + 2] & 0xff) << 16)
+ | ((buffer[p + 3] & 0xff) << 24));
+ }
+
+ private long readLittleEndian64_NoCheck() {
+ int p = pos;
+ final byte[] buffer = this.buffer;
+ pos = p + FIXED64_SIZE;
+ return (((buffer[p] & 0xffL))
+ | ((buffer[p + 1] & 0xffL) << 8)
+ | ((buffer[p + 2] & 0xffL) << 16)
+ | ((buffer[p + 3] & 0xffL) << 24)
+ | ((buffer[p + 4] & 0xffL) << 32)
+ | ((buffer[p + 5] & 0xffL) << 40)
+ | ((buffer[p + 6] & 0xffL) << 48)
+ | ((buffer[p + 7] & 0xffL) << 56));
+ }
+
+ private void skipVarint() throws IOException {
+ if (limit - pos >= 10) {
+ final byte[] buffer = this.buffer;
+ int p = pos;
+ for (int i = 0; i < 10; i++) {
+ if (buffer[p++] >= 0) {
+ pos = p;
+ return;
+ }
+ }
+ }
+ skipVarintSlowPath();
+ }
+
+ private void skipVarintSlowPath() throws IOException {
+ for (int i = 0; i < 10; i++) {
+ if (readByte() >= 0) {
+ return;
+ }
+ }
+ throw InvalidProtocolBufferException.malformedVarint();
+ }
+
+ private void skipBytes(final int size) throws IOException {
+ requireBytes(size);
+
+ pos += size;
+ }
+
+ private void skipGroup() throws IOException {
+ int prevEndGroupTag = endGroupTag;
+ endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
+ while (true) {
+ if (getFieldNumber() == READ_DONE || !skipField()) {
+ break;
+ }
+ }
+ if (tag != endGroupTag) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ endGroupTag = prevEndGroupTag;
+ }
+
+ private void requireBytes(int size) throws IOException {
+ if (size < 0 || size > (limit - pos)) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+
+ private void requireWireType(int requiredWireType) throws IOException {
+ if (WireFormat.getTagWireType(tag) != requiredWireType) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ private void verifyPackedFixed64Length(int bytes) throws IOException {
+ requireBytes(bytes);
+ if ((bytes & FIXED64_MULTIPLE_MASK) != 0) {
+ // Require that the number of bytes be a multiple of 8.
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+
+ private void verifyPackedFixed32Length(int bytes) throws IOException {
+ requireBytes(bytes);
+ if ((bytes & FIXED32_MULTIPLE_MASK) != 0) {
+ // Require that the number of bytes be a multiple of 4.
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+
+ private void requirePosition(int expectedPosition) throws IOException {
+ if (pos != expectedPosition) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java
new file mode 100755
index 000000000..b1dbb8bf4
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java
@@ -0,0 +1,3071 @@
+// 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 static com.google.protobuf.WireFormat.FIXED32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED64_SIZE;
+import static com.google.protobuf.WireFormat.MAX_VARINT32_SIZE;
+import static com.google.protobuf.WireFormat.MAX_VARINT64_SIZE;
+import static com.google.protobuf.WireFormat.MESSAGE_SET_ITEM;
+import static com.google.protobuf.WireFormat.MESSAGE_SET_MESSAGE;
+import static com.google.protobuf.WireFormat.MESSAGE_SET_TYPE_ID;
+import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
+import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
+import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayDeque;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+
+/**
+ * A protobuf writer that serializes messages in their binary form. Messages are serialized in
+ * reverse in order to avoid calculating the serialized size of each nested message. Since the
+ * message size is not known in advance, the writer employs a strategy of chunking and buffer
+ * chaining. Buffers are allocated as-needed by a provided {@link BufferAllocator}. Once writing is
+ * finished, the application can access the buffers in forward-writing order by calling {@link
+ * #complete()}.
+ *
+ * <p>Once {@link #complete()} has been called, the writer can not be reused for additional writes.
+ * The {@link #getTotalBytesWritten()} will continue to reflect the total of the write and will not
+ * be reset.
+ */
+@ExperimentalApi
+abstract class BinaryWriter extends ByteOutput implements Writer {
+ public static final int DEFAULT_CHUNK_SIZE = 4096;
+
+ private final BufferAllocator alloc;
+ private final int chunkSize;
+
+ final ArrayDeque<AllocatedBuffer> buffers = new ArrayDeque<AllocatedBuffer>(4);
+ int totalDoneBytes;
+
+ /**
+ * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@link
+ * #DEFAULT_CHUNK_SIZE} as necessary.
+ */
+ public static BinaryWriter newHeapInstance(BufferAllocator alloc) {
+ return newHeapInstance(alloc, DEFAULT_CHUNK_SIZE);
+ }
+
+ /**
+ * Creates a new {@link BinaryWriter} that will allocate heap buffers of {@code chunkSize} as
+ * necessary.
+ */
+ public static BinaryWriter newHeapInstance(BufferAllocator alloc, int chunkSize) {
+ return isUnsafeHeapSupported()
+ ? newUnsafeHeapInstance(alloc, chunkSize)
+ : newSafeHeapInstance(alloc, chunkSize);
+ }
+
+ /**
+ * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@link
+ * #DEFAULT_CHUNK_SIZE} as necessary.
+ */
+ public static BinaryWriter newDirectInstance(BufferAllocator alloc) {
+ return newDirectInstance(alloc, DEFAULT_CHUNK_SIZE);
+ }
+
+ /**
+ * Creates a new {@link BinaryWriter} that will allocate direct (i.e. non-heap) buffers of {@code
+ * chunkSize} as necessary.
+ */
+ public static BinaryWriter newDirectInstance(BufferAllocator alloc, int chunkSize) {
+ return isUnsafeDirectSupported()
+ ? newUnsafeDirectInstance(alloc, chunkSize)
+ : newSafeDirectInstance(alloc, chunkSize);
+ }
+
+ static boolean isUnsafeHeapSupported() {
+ return UnsafeHeapWriter.isSupported();
+ }
+
+ static boolean isUnsafeDirectSupported() {
+ return UnsafeDirectWriter.isSupported();
+ }
+
+ static BinaryWriter newSafeHeapInstance(BufferAllocator alloc, int chunkSize) {
+ return new SafeHeapWriter(alloc, chunkSize);
+ }
+
+ static BinaryWriter newUnsafeHeapInstance(BufferAllocator alloc, int chunkSize) {
+ if (!isUnsafeHeapSupported()) {
+ throw new UnsupportedOperationException("Unsafe operations not supported");
+ }
+ return new UnsafeHeapWriter(alloc, chunkSize);
+ }
+
+ static BinaryWriter newSafeDirectInstance(BufferAllocator alloc, int chunkSize) {
+ return new SafeDirectWriter(alloc, chunkSize);
+ }
+
+ static BinaryWriter newUnsafeDirectInstance(BufferAllocator alloc, int chunkSize) {
+ if (!isUnsafeDirectSupported()) {
+ throw new UnsupportedOperationException("Unsafe operations not supported");
+ }
+ return new UnsafeDirectWriter(alloc, chunkSize);
+ }
+
+ /** Only allow subclassing for inner classes. */
+ private BinaryWriter(BufferAllocator alloc, int chunkSize) {
+ if (chunkSize <= 0) {
+ throw new IllegalArgumentException("chunkSize must be > 0");
+ }
+ this.alloc = checkNotNull(alloc, "alloc");
+ this.chunkSize = chunkSize;
+ }
+
+ @Override
+ public final FieldOrder fieldOrder() {
+ return FieldOrder.DESCENDING;
+ }
+
+ /**
+ * Completes the write operation and returns a queue of {@link AllocatedBuffer} objects in
+ * forward-writing order. This method should only be called once.
+ *
+ * <p>After calling this method, the writer can not be reused. Create a new writer for future
+ * writes.
+ */
+ public final Queue<AllocatedBuffer> complete() {
+ finishCurrentBuffer();
+ return buffers;
+ }
+
+ @Override
+ public final void writeSFixed32(int fieldNumber, int value) throws IOException {
+ writeFixed32(fieldNumber, value);
+ }
+
+ @Override
+ public final void writeInt64(int fieldNumber, long value) throws IOException {
+ writeUInt64(fieldNumber, value);
+ }
+
+ @Override
+ public final void writeSFixed64(int fieldNumber, long value) throws IOException {
+ writeFixed64(fieldNumber, value);
+ }
+
+ @Override
+ public final void writeFloat(int fieldNumber, float value) throws IOException {
+ writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
+ }
+
+ @Override
+ public final void writeDouble(int fieldNumber, double value) throws IOException {
+ writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
+ }
+
+ @Override
+ public final void writeEnum(int fieldNumber, int value) throws IOException {
+ writeInt32(fieldNumber, value);
+ }
+
+ @Override
+ public final void writeInt32List(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (list instanceof IntArrayList) {
+ writeInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
+ } else {
+ writeInt32List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeInt32(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeInt32(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeInt32(list.getInt(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeInt32(fieldNumber, list.getInt(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed32List(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (list instanceof IntArrayList) {
+ writeFixed32List_Internal(fieldNumber, (IntArrayList) list, packed);
+ } else {
+ writeFixed32List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeFixed32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(list.getInt(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(fieldNumber, list.getInt(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeInt64List(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ writeUInt64List(fieldNumber, list, packed);
+ }
+
+ @Override
+ public final void writeUInt64List(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (list instanceof LongArrayList) {
+ writeUInt64List_Internal(fieldNumber, (LongArrayList) list, packed);
+ } else {
+ writeUInt64List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeUInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeVarint64(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeUInt64(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeVarint64(list.getLong(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeUInt64(fieldNumber, list.getLong(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed64List(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (list instanceof LongArrayList) {
+ writeFixed64List_Internal(fieldNumber, (LongArrayList) list, packed);
+ } else {
+ writeFixed64List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeFixed64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(list.getLong(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(fieldNumber, list.getLong(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeFloatList(int fieldNumber, List<Float> list, boolean packed)
+ throws IOException {
+ if (list instanceof FloatArrayList) {
+ writeFloatList_Internal(fieldNumber, (FloatArrayList) list, packed);
+ } else {
+ writeFloatList_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeFloatList_Internal(int fieldNumber, List<Float> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(Float.floatToRawIntBits(list.get(i)));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFloat(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed32(Float.floatToRawIntBits(list.getFloat(i)));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFloat(fieldNumber, list.getFloat(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeDoubleList(int fieldNumber, List<Double> list, boolean packed)
+ throws IOException {
+ if (list instanceof DoubleArrayList) {
+ writeDoubleList_Internal(fieldNumber, (DoubleArrayList) list, packed);
+ } else {
+ writeDoubleList_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeDoubleList_Internal(int fieldNumber, List<Double> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(Double.doubleToRawLongBits(list.get(i)));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeDouble(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeFixed64(Double.doubleToRawLongBits(list.getDouble(i)));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeDouble(fieldNumber, list.getDouble(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeEnumList(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ writeInt32List(fieldNumber, list, packed);
+ }
+
+ @Override
+ public final void writeBoolList(int fieldNumber, List<Boolean> list, boolean packed)
+ throws IOException {
+ if (list instanceof BooleanArrayList) {
+ writeBoolList_Internal(fieldNumber, (BooleanArrayList) list, packed);
+ } else {
+ writeBoolList_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeBoolList_Internal(int fieldNumber, List<Boolean> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeBool(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeBool(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeBool(list.getBoolean(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeBool(fieldNumber, list.getBoolean(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeStringList(int fieldNumber, List<String> list) throws IOException {
+ if (list instanceof LazyStringList) {
+ final LazyStringList lazyList = (LazyStringList) list;
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeLazyString(fieldNumber, lazyList.getRaw(i));
+ }
+ } else {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeString(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private void writeLazyString(int fieldNumber, Object value) throws IOException {
+ if (value instanceof String) {
+ writeString(fieldNumber, (String) value);
+ } else {
+ writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ @Override
+ public final void writeBytesList(int fieldNumber, List<ByteString> list) throws IOException {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeBytes(fieldNumber, list.get(i));
+ }
+ }
+
+ @Override
+ public final void writeUInt32List(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (list instanceof IntArrayList) {
+ writeUInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
+ } else {
+ writeUInt32List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeUInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeVarint32(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeUInt32(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeVarint32(list.getInt(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeUInt32(fieldNumber, list.getInt(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeSFixed32List(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ writeFixed32List(fieldNumber, list, packed);
+ }
+
+ @Override
+ public final void writeSFixed64List(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ writeFixed64List(fieldNumber, list, packed);
+ }
+
+ @Override
+ public final void writeSInt32List(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (list instanceof IntArrayList) {
+ writeSInt32List_Internal(fieldNumber, (IntArrayList) list, packed);
+ } else {
+ writeSInt32List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private final void writeSInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt32(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt32(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt32(list.getInt(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt32(fieldNumber, list.getInt(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeSInt64List(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (list instanceof LongArrayList) {
+ writeSInt64List_Internal(fieldNumber, (LongArrayList) list, packed);
+ } else {
+ writeSInt64List_Internal(fieldNumber, list, packed);
+ }
+ }
+
+ private static final int MAP_KEY_NUMBER = 1;
+ private static final int MAP_VALUE_NUMBER = 2;
+
+ @Override
+ public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
+ throws IOException {
+ // TODO(liujisi): Reverse write those entries.
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ int prevBytes = getTotalBytesWritten();
+ writeMapEntryField(this, MAP_VALUE_NUMBER, metadata.valueType, entry.getValue());
+ writeMapEntryField(this, MAP_KEY_NUMBER, metadata.keyType, entry.getKey());
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+ }
+
+ static final void writeMapEntryField(
+ Writer writer, int fieldNumber, WireFormat.FieldType fieldType, Object object)
+ throws IOException {
+ switch (fieldType) {
+ case BOOL:
+ writer.writeBool(fieldNumber, (Boolean) object);
+ break;
+ case FIXED32:
+ writer.writeFixed32(fieldNumber, (Integer) object);
+ break;
+ case FIXED64:
+ writer.writeFixed64(fieldNumber, (Long) object);
+ break;
+ case INT32:
+ writer.writeInt32(fieldNumber, (Integer) object);
+ break;
+ case INT64:
+ writer.writeInt64(fieldNumber, (Long) object);
+ break;
+ case SFIXED32:
+ writer.writeSFixed32(fieldNumber, (Integer) object);
+ break;
+ case SFIXED64:
+ writer.writeSFixed64(fieldNumber, (Long) object);
+ break;
+ case SINT32:
+ writer.writeSInt32(fieldNumber, (Integer) object);
+ break;
+ case SINT64:
+ writer.writeSInt64(fieldNumber, (Long) object);
+ break;
+ case STRING:
+ writer.writeString(fieldNumber, (String) object);
+ break;
+ case UINT32:
+ writer.writeUInt32(fieldNumber, (Integer) object);
+ break;
+ case UINT64:
+ writer.writeUInt64(fieldNumber, (Long) object);
+ break;
+ case FLOAT:
+ writer.writeFloat(fieldNumber, (Float) object);
+ break;
+ case DOUBLE:
+ writer.writeDouble(fieldNumber, (Double) object);
+ break;
+ case MESSAGE:
+ writer.writeMessage(fieldNumber, object);
+ break;
+ case BYTES:
+ writer.writeBytes(fieldNumber, (ByteString) object);
+ break;
+ case ENUM:
+ if (object instanceof Internal.EnumLite) {
+ writer.writeEnum(fieldNumber, ((Internal.EnumLite) object).getNumber());
+ } else if (object instanceof Integer) {
+ writer.writeEnum(fieldNumber, (Integer) object);
+ } else {
+ throw new IllegalArgumentException("Unexpected type for enum in map.");
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported map value type for: " + fieldType);
+ }
+ }
+
+ private final void writeSInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt64(list.get(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt64(fieldNumber, list.get(i));
+ }
+ }
+ }
+
+ private final void writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+ throws IOException {
+ if (packed) {
+ requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
+ int prevBytes = getTotalBytesWritten();
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt64(list.getLong(i));
+ }
+ int length = getTotalBytesWritten() - prevBytes;
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ } else {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ writeSInt64(fieldNumber, list.getLong(i));
+ }
+ }
+ }
+
+ @Override
+ public final void writeMessageList(int fieldNumber, List<?> list) throws IOException {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeMessage(fieldNumber, list.get(i));
+ }
+ }
+
+ @Override
+ public final void writeMessageList(int fieldNumber, List<?> list, Schema schema)
+ throws IOException {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeMessage(fieldNumber, list.get(i), schema);
+ }
+ }
+
+ @Override
+ public final void writeGroupList(int fieldNumber, List<?> list) throws IOException {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeGroup(fieldNumber, list.get(i));
+ }
+ }
+
+ @Override
+ public final void writeGroupList(int fieldNumber, List<?> list, Schema schema)
+ throws IOException {
+ for (int i = list.size() - 1; i >= 0; i--) {
+ writeGroup(fieldNumber, list.get(i), schema);
+ }
+ }
+
+ @Override
+ public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException {
+ writeTag(MESSAGE_SET_ITEM, WIRETYPE_END_GROUP);
+ if (value instanceof ByteString) {
+ writeBytes(MESSAGE_SET_MESSAGE, (ByteString) value);
+ } else {
+ writeMessage(MESSAGE_SET_MESSAGE, value);
+ }
+ writeUInt32(MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeTag(MESSAGE_SET_ITEM, WIRETYPE_START_GROUP);
+ }
+
+ final AllocatedBuffer newHeapBuffer() {
+ return alloc.allocateHeapBuffer(chunkSize);
+ }
+
+ final AllocatedBuffer newHeapBuffer(int capacity) {
+ return alloc.allocateHeapBuffer(Math.max(capacity, chunkSize));
+ }
+
+ final AllocatedBuffer newDirectBuffer() {
+ return alloc.allocateDirectBuffer(chunkSize);
+ }
+
+ final AllocatedBuffer newDirectBuffer(int capacity) {
+ return alloc.allocateDirectBuffer(Math.max(capacity, chunkSize));
+ }
+
+ /**
+ * Gets the total number of bytes that have been written. This will not be reset by a call to
+ * {@link #complete()}.
+ */
+ public abstract int getTotalBytesWritten();
+
+ abstract void requireSpace(int size);
+
+ abstract void finishCurrentBuffer();
+
+ abstract void writeTag(int fieldNumber, int wireType);
+
+ abstract void writeVarint32(int value);
+
+ abstract void writeInt32(int value);
+
+ abstract void writeSInt32(int value);
+
+ abstract void writeFixed32(int value);
+
+ abstract void writeVarint64(long value);
+
+ abstract void writeSInt64(long value);
+
+ abstract void writeFixed64(long value);
+
+ abstract void writeBool(boolean value);
+
+ abstract void writeString(String in);
+
+ /**
+ * Not using the version in CodedOutputStream due to the fact that benchmarks have shown a
+ * performance improvement when returning a byte (rather than an int).
+ */
+ private static byte computeUInt64SizeNoTag(long value) {
+ // handle two popular special cases up front ...
+ if ((value & (~0L << 7)) == 0L) {
+ // Byte 1
+ return 1;
+ }
+ if (value < 0L) {
+ // Byte 10
+ return 10;
+ }
+ // ... leaving us with 8 remaining, which we can divide and conquer
+ byte n = 2;
+ if ((value & (~0L << 35)) != 0L) {
+ // Byte 6-9
+ n += 4; // + (value >>> 63);
+ value >>>= 28;
+ }
+ if ((value & (~0L << 21)) != 0L) {
+ // Byte 4-5 or 8-9
+ n += 2;
+ value >>>= 14;
+ }
+ if ((value & (~0L << 14)) != 0L) {
+ // Byte 3 or 7
+ n += 1;
+ }
+ return n;
+ }
+
+ /** Writer that uses safe operations on target array. */
+ private static final class SafeHeapWriter extends BinaryWriter {
+ private AllocatedBuffer allocatedBuffer;
+ private byte[] buffer;
+ private int offset;
+ private int limit;
+ private int offsetMinusOne;
+ private int limitMinusOne;
+ private int pos;
+
+ SafeHeapWriter(BufferAllocator alloc, int chunkSize) {
+ super(alloc, chunkSize);
+ nextBuffer();
+ }
+
+ @Override
+ void finishCurrentBuffer() {
+ if (allocatedBuffer != null) {
+ totalDoneBytes += bytesWrittenToCurrentBuffer();
+ allocatedBuffer.position((pos - allocatedBuffer.arrayOffset()) + 1);
+ allocatedBuffer = null;
+ pos = 0;
+ limitMinusOne = 0;
+ }
+ }
+
+ private void nextBuffer() {
+ nextBuffer(newHeapBuffer());
+ }
+
+ private void nextBuffer(int capacity) {
+ nextBuffer(newHeapBuffer(capacity));
+ }
+
+ private void nextBuffer(AllocatedBuffer allocatedBuffer) {
+ if (!allocatedBuffer.hasArray()) {
+ throw new RuntimeException("Allocator returned non-heap buffer");
+ }
+
+ finishCurrentBuffer();
+
+ buffers.addFirst(allocatedBuffer);
+
+ this.allocatedBuffer = allocatedBuffer;
+ this.buffer = allocatedBuffer.array();
+ int arrayOffset = allocatedBuffer.arrayOffset();
+ this.limit = arrayOffset + allocatedBuffer.limit();
+ this.offset = arrayOffset + allocatedBuffer.position();
+ this.offsetMinusOne = offset - 1;
+ this.limitMinusOne = limit - 1;
+ this.pos = limitMinusOne;
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return totalDoneBytes + bytesWrittenToCurrentBuffer();
+ }
+
+ int bytesWrittenToCurrentBuffer() {
+ return limitMinusOne - pos;
+ }
+
+ int spaceLeft() {
+ return pos - offsetMinusOne;
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt32(int fieldNumber, int value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeSInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
+ writeFixed32(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED32);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeVarint64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt64(int fieldNumber, long value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeSInt64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
+ writeFixed64(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED64);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) throws IOException {
+ requireSpace(MAX_VARINT32_SIZE + 1);
+ write((byte) (value ? 1 : 0));
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ writeString(value);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(2 * MAX_VARINT32_SIZE);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+ try {
+ value.writeToReverse(this);
+ } catch (IOException e) {
+ // Should never happen since the writer does not throw.
+ throw new RuntimeException(e);
+ }
+
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value.size());
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ Protobuf.getInstance().writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ schema.writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ Protobuf.getInstance().writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ schema.writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeStartGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeEndGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ void writeInt32(int value) {
+ if (value >= 0) {
+ writeVarint32(value);
+ } else {
+ writeVarint64(value);
+ }
+ }
+
+ @Override
+ void writeSInt32(int value) {
+ writeVarint32(CodedOutputStream.encodeZigZag32(value));
+ }
+
+ @Override
+ void writeSInt64(long value) {
+ writeVarint64(CodedOutputStream.encodeZigZag64(value));
+ }
+
+ @Override
+ void writeBool(boolean value) {
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ void writeTag(int fieldNumber, int wireType) {
+ writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ void writeVarint32(int value) {
+ if ((value & (~0 << 7)) == 0) {
+ writeVarint32OneByte(value);
+ } else if ((value & (~0 << 14)) == 0) {
+ writeVarint32TwoBytes(value);
+ } else if ((value & (~0 << 21)) == 0) {
+ writeVarint32ThreeBytes(value);
+ } else if ((value & (~0 << 28)) == 0) {
+ writeVarint32FourBytes(value);
+ } else {
+ writeVarint32FiveBytes(value);
+ }
+ }
+
+ private void writeVarint32OneByte(int value) {
+ buffer[pos--] = (byte) value;
+ }
+
+ private void writeVarint32TwoBytes(int value) {
+ buffer[pos--] = (byte) (value >>> 7);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint32ThreeBytes(int value) {
+ buffer[pos--] = (byte) (value >>> 14);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint32FourBytes(int value) {
+ buffer[pos--] = (byte) (value >>> 21);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint32FiveBytes(int value) {
+ buffer[pos--] = (byte) (value >>> 28);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ @Override
+ void writeVarint64(long value) {
+ switch (computeUInt64SizeNoTag(value)) {
+ case 1:
+ writeVarint64OneByte(value);
+ break;
+ case 2:
+ writeVarint64TwoBytes(value);
+ break;
+ case 3:
+ writeVarint64ThreeBytes(value);
+ break;
+ case 4:
+ writeVarint64FourBytes(value);
+ break;
+ case 5:
+ writeVarint64FiveBytes(value);
+ break;
+ case 6:
+ writeVarint64SixBytes(value);
+ break;
+ case 7:
+ writeVarint64SevenBytes(value);
+ break;
+ case 8:
+ writeVarint64EightBytes(value);
+ break;
+ case 9:
+ writeVarint64NineBytes(value);
+ break;
+ case 10:
+ writeVarint64TenBytes(value);
+ break;
+ }
+ }
+
+ private void writeVarint64OneByte(long value) {
+ buffer[pos--] = (byte) value;
+ }
+
+ private void writeVarint64TwoBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 7);
+ buffer[pos--] = (byte) (((int) value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64ThreeBytes(long value) {
+ buffer[pos--] = (byte) (((int) value) >>> 14);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64FourBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 21);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64FiveBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 28);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64SixBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 35);
+ buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64SevenBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 42);
+ buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64EightBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 49);
+ buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64NineBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 56);
+ buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ private void writeVarint64TenBytes(long value) {
+ buffer[pos--] = (byte) (value >>> 63);
+ buffer[pos--] = (byte) (((value >>> 56) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 49) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 42) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 35) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 28) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 21) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 14) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) (((value >>> 7) & 0x7F) | 0x80);
+ buffer[pos--] = (byte) ((value & 0x7F) | 0x80);
+ }
+
+ @Override
+ void writeFixed32(int value) {
+ buffer[pos--] = (byte) ((value >> 24) & 0xFF);
+ buffer[pos--] = (byte) ((value >> 16) & 0xFF);
+ buffer[pos--] = (byte) ((value >> 8) & 0xFF);
+ buffer[pos--] = (byte) (value & 0xFF);
+ }
+
+ @Override
+ void writeFixed64(long value) {
+ buffer[pos--] = (byte) ((int) (value >> 56) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 48) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 40) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 32) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 24) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 16) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value >> 8) & 0xFF);
+ buffer[pos--] = (byte) ((int) (value) & 0xFF);
+ }
+
+ @Override
+ void writeString(String in) {
+ // Request enough space to write the ASCII string.
+ requireSpace(in.length());
+
+ // We know the buffer is big enough...
+ int i = in.length() - 1;
+ // Set pos to the start of the ASCII string.
+ pos -= i;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
+ buffer[pos + i] = (byte) c;
+ }
+ if (i == -1) {
+ // Move pos past the String.
+ pos -= 1;
+ return;
+ }
+ pos += i;
+ for (char c; i >= 0; i--) {
+ c = in.charAt(i);
+ if (c < 0x80 && pos > offsetMinusOne) {
+ buffer[pos--] = (byte) c;
+ } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes
+ buffer[pos--] = (byte) (0x80 | (0x3F & c));
+ buffer[pos--] = (byte) ((0xF << 6) | (c >>> 6));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
+ && pos > (offset + 1)) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ buffer[pos--] = (byte) (0x80 | (0x3F & c));
+ buffer[pos--] = (byte) (0x80 | (0x3F & (c >>> 6)));
+ buffer[pos--] = (byte) ((0xF << 5) | (c >>> 12));
+ } else if (pos > (offset + 2)) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+ // four UTF-8 bytes
+ char high = 0;
+ if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
+ throw new Utf8.UnpairedSurrogateException(i - 1, i);
+ }
+ i--;
+ int codePoint = Character.toCodePoint(high, c);
+ buffer[pos--] = (byte) (0x80 | (0x3F & codePoint));
+ buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+ buffer[pos--] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+ buffer[pos--] = (byte) ((0xF << 4) | (codePoint >>> 18));
+ } else {
+ // Buffer is full - allocate a new one and revisit the current character.
+ requireSpace(i);
+ i++;
+ }
+ }
+ }
+
+ @Override
+ public void write(byte value) {
+ buffer[pos--] = value;
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ System.arraycopy(value, offset, buffer, pos + 1, length);
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ System.arraycopy(value, offset, buffer, pos + 1, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ value.get(buffer, pos + 1, length);
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ }
+
+ pos -= length;
+ value.get(buffer, pos + 1, length);
+ }
+
+ @Override
+ void requireSpace(int size) {
+ if (spaceLeft() < size) {
+ nextBuffer(size);
+ }
+ }
+ }
+
+ /** Writer that uses unsafe operations on a target array. */
+ private static final class UnsafeHeapWriter extends BinaryWriter {
+ private AllocatedBuffer allocatedBuffer;
+ private byte[] buffer;
+ private long offset;
+ private long limit;
+ private long offsetMinusOne;
+ private long limitMinusOne;
+ private long pos;
+
+ UnsafeHeapWriter(BufferAllocator alloc, int chunkSize) {
+ super(alloc, chunkSize);
+ nextBuffer();
+ }
+
+ /** Indicates whether the required unsafe operations are supported on this platform. */
+ static boolean isSupported() {
+ return UnsafeUtil.hasUnsafeArrayOperations();
+ }
+
+ @Override
+ void finishCurrentBuffer() {
+ if (allocatedBuffer != null) {
+ totalDoneBytes += bytesWrittenToCurrentBuffer();
+ allocatedBuffer.position((arrayPos() - allocatedBuffer.arrayOffset()) + 1);
+ allocatedBuffer = null;
+ pos = 0;
+ limitMinusOne = 0;
+ }
+ }
+
+ private int arrayPos() {
+ return (int) pos;
+ }
+
+ private void nextBuffer() {
+ nextBuffer(newHeapBuffer());
+ }
+
+ private void nextBuffer(int capacity) {
+ nextBuffer(newHeapBuffer(capacity));
+ }
+
+ private void nextBuffer(AllocatedBuffer allocatedBuffer) {
+ if (!allocatedBuffer.hasArray()) {
+ throw new RuntimeException("Allocator returned non-heap buffer");
+ }
+
+ finishCurrentBuffer();
+ buffers.addFirst(allocatedBuffer);
+
+ this.allocatedBuffer = allocatedBuffer;
+ this.buffer = allocatedBuffer.array();
+ int arrayOffset = allocatedBuffer.arrayOffset();
+ this.limit = arrayOffset + allocatedBuffer.limit();
+ this.offset = arrayOffset + allocatedBuffer.position();
+ this.offsetMinusOne = offset - 1;
+ this.limitMinusOne = limit - 1;
+ this.pos = limitMinusOne;
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return totalDoneBytes + bytesWrittenToCurrentBuffer();
+ }
+
+ int bytesWrittenToCurrentBuffer() {
+ return (int) (limitMinusOne - pos);
+ }
+
+ int spaceLeft() {
+ return (int) (pos - offsetMinusOne);
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeSInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
+ writeFixed32(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED32);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeVarint64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeSInt64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
+ writeFixed64(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED64);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) {
+ requireSpace(MAX_VARINT32_SIZE + 1);
+ write((byte) (value ? 1 : 0));
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) {
+ int prevBytes = getTotalBytesWritten();
+ writeString(value);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(2 * MAX_VARINT32_SIZE);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) {
+ try {
+ value.writeToReverse(this);
+ } catch (IOException e) {
+ // Should never happen since the writer does not throw.
+ throw new RuntimeException(e);
+ }
+
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value.size());
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ Protobuf.getInstance().writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ schema.writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ Protobuf.getInstance().writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ schema.writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeStartGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeEndGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ void writeInt32(int value) {
+ if (value >= 0) {
+ writeVarint32(value);
+ } else {
+ writeVarint64(value);
+ }
+ }
+
+ @Override
+ void writeSInt32(int value) {
+ writeVarint32(CodedOutputStream.encodeZigZag32(value));
+ }
+
+ @Override
+ void writeSInt64(long value) {
+ writeVarint64(CodedOutputStream.encodeZigZag64(value));
+ }
+
+ @Override
+ void writeBool(boolean value) {
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ void writeTag(int fieldNumber, int wireType) {
+ writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ void writeVarint32(int value) {
+ if ((value & (~0 << 7)) == 0) {
+ writeVarint32OneByte(value);
+ } else if ((value & (~0 << 14)) == 0) {
+ writeVarint32TwoBytes(value);
+ } else if ((value & (~0 << 21)) == 0) {
+ writeVarint32ThreeBytes(value);
+ } else if ((value & (~0 << 28)) == 0) {
+ writeVarint32FourBytes(value);
+ } else {
+ writeVarint32FiveBytes(value);
+ }
+ }
+
+ private void writeVarint32OneByte(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) value);
+ }
+
+ private void writeVarint32TwoBytes(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32ThreeBytes(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 14));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32FourBytes(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32FiveBytes(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ @Override
+ void writeVarint64(long value) {
+ switch (computeUInt64SizeNoTag(value)) {
+ case 1:
+ writeVarint64OneByte(value);
+ break;
+ case 2:
+ writeVarint64TwoBytes(value);
+ break;
+ case 3:
+ writeVarint64ThreeBytes(value);
+ break;
+ case 4:
+ writeVarint64FourBytes(value);
+ break;
+ case 5:
+ writeVarint64FiveBytes(value);
+ break;
+ case 6:
+ writeVarint64SixBytes(value);
+ break;
+ case 7:
+ writeVarint64SevenBytes(value);
+ break;
+ case 8:
+ writeVarint64EightBytes(value);
+ break;
+ case 9:
+ writeVarint64NineBytes(value);
+ break;
+ case 10:
+ writeVarint64TenBytes(value);
+ break;
+ }
+ }
+
+ private void writeVarint64OneByte(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) value);
+ }
+
+ private void writeVarint64TwoBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 7));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64ThreeBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((int) value) >>> 14));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64FourBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 21));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64FiveBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 28));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64SixBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 35));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64SevenBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 42));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64EightBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 49));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64NineBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 56));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64TenBytes(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value >>> 63));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ @Override
+ void writeFixed32(int value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 24) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 16) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((value >> 8) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (value & 0xFF));
+ }
+
+ @Override
+ void writeFixed64(long value) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 56) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 48) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 40) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 32) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 24) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 16) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value >> 8) & 0xFF));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((int) (value) & 0xFF));
+ }
+
+ @Override
+ void writeString(String in) {
+ // Request enough space to write the ASCII string.
+ requireSpace(in.length());
+
+ // We know the buffer is big enough...
+ int i = in.length() - 1;
+ // Set pos to the start of the ASCII string.
+ // pos -= i;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) c);
+ }
+ if (i == -1) {
+ // Move pos past the String.
+ return;
+ }
+ for (char c; i >= 0; i--) {
+ c = in.charAt(i);
+ if (c < 0x80 && pos > offsetMinusOne) {
+ UnsafeUtil.putByte(buffer, pos--, (byte) c);
+ } else if (c < 0x800 && pos > offset) { // 11 bits, two UTF-8 bytes
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c)));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 6) | (c >>> 6)));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
+ && pos > offset + 1) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & c)));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 5) | (c >>> 12)));
+ } else if (pos > offset + 2) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+ // four UTF-8 bytes
+ final char high;
+ if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
+ throw new Utf8.UnpairedSurrogateException(i - 1, i);
+ }
+ i--;
+ int codePoint = Character.toCodePoint(high, c);
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & codePoint)));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UnsafeUtil.putByte(buffer, pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UnsafeUtil.putByte(buffer, pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ } else {
+ // Buffer is full - allocate a new one and revisit the current character.
+ requireSpace(i);
+ i++;
+ }
+ }
+ }
+
+ @Override
+ public void write(byte value) {
+ UnsafeUtil.putByte(buffer, pos--, value);
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) {
+ if (offset < 0 || offset + length > value.length) {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length));
+ }
+ requireSpace(length);
+
+ pos -= length;
+ System.arraycopy(value, offset, buffer, arrayPos() + 1, length);
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) {
+ if (offset < 0 || offset + length > value.length) {
+ throw new ArrayIndexOutOfBoundsException(
+ String.format("value.length=%d, offset=%d, length=%d", value.length, offset, length));
+ }
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ System.arraycopy(value, offset, buffer, arrayPos() + 1, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) {
+ int length = value.remaining();
+ requireSpace(length);
+
+ pos -= length;
+ value.get(buffer, arrayPos() + 1, length);
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ }
+
+ pos -= length;
+ value.get(buffer, arrayPos() + 1, length);
+ }
+
+ @Override
+ void requireSpace(int size) {
+ if (spaceLeft() < size) {
+ nextBuffer(size);
+ }
+ }
+ }
+
+ /** Writer that uses safe operations on a target {@link ByteBuffer}. */
+ private static final class SafeDirectWriter extends BinaryWriter {
+ private ByteBuffer buffer;
+ private int limitMinusOne;
+ private int pos;
+
+ SafeDirectWriter(BufferAllocator alloc, int chunkSize) {
+ super(alloc, chunkSize);
+ nextBuffer();
+ }
+
+ private void nextBuffer() {
+ nextBuffer(newDirectBuffer());
+ }
+
+ private void nextBuffer(int capacity) {
+ nextBuffer(newDirectBuffer(capacity));
+ }
+
+ private void nextBuffer(AllocatedBuffer allocatedBuffer) {
+ if (!allocatedBuffer.hasNioBuffer()) {
+ throw new RuntimeException("Allocated buffer does not have NIO buffer");
+ }
+ ByteBuffer nioBuffer = allocatedBuffer.nioBuffer();
+ if (!nioBuffer.isDirect()) {
+ throw new RuntimeException("Allocator returned non-direct buffer");
+ }
+
+ finishCurrentBuffer();
+ buffers.addFirst(allocatedBuffer);
+
+ buffer = nioBuffer;
+ buffer.limit(buffer.capacity());
+ buffer.position(0);
+ // Set byte order to little endian for fast writing of fixed 32/64.
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ limitMinusOne = buffer.limit() - 1;
+ pos = limitMinusOne;
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return totalDoneBytes + bytesWrittenToCurrentBuffer();
+ }
+
+ private int bytesWrittenToCurrentBuffer() {
+ return limitMinusOne - pos;
+ }
+
+ private int spaceLeft() {
+ return pos + 1;
+ }
+
+ @Override
+ void finishCurrentBuffer() {
+ if (buffer != null) {
+ totalDoneBytes += bytesWrittenToCurrentBuffer();
+ // Update the indices on the netty buffer.
+ buffer.position(pos + 1);
+ buffer = null;
+ pos = 0;
+ limitMinusOne = 0;
+ }
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeSInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
+ writeFixed32(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED32);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeVarint64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeSInt64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
+ writeFixed64(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED64);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) {
+ requireSpace(MAX_VARINT32_SIZE + 1);
+ write((byte) (value ? 1 : 0));
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) {
+ int prevBytes = getTotalBytesWritten();
+ writeString(value);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(2 * MAX_VARINT32_SIZE);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) {
+ try {
+ value.writeToReverse(this);
+ } catch (IOException e) {
+ // Should never happen since the writer does not throw.
+ throw new RuntimeException(e);
+ }
+
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value.size());
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ Protobuf.getInstance().writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ schema.writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ Protobuf.getInstance().writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ schema.writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeStartGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeEndGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ void writeInt32(int value) {
+ if (value >= 0) {
+ writeVarint32(value);
+ } else {
+ writeVarint64(value);
+ }
+ }
+
+ @Override
+ void writeSInt32(int value) {
+ writeVarint32(CodedOutputStream.encodeZigZag32(value));
+ }
+
+ @Override
+ void writeSInt64(long value) {
+ writeVarint64(CodedOutputStream.encodeZigZag64(value));
+ }
+
+ @Override
+ void writeBool(boolean value) {
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ void writeTag(int fieldNumber, int wireType) {
+ writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ void writeVarint32(int value) {
+ if ((value & (~0 << 7)) == 0) {
+ writeVarint32OneByte(value);
+ } else if ((value & (~0 << 14)) == 0) {
+ writeVarint32TwoBytes(value);
+ } else if ((value & (~0 << 21)) == 0) {
+ writeVarint32ThreeBytes(value);
+ } else if ((value & (~0 << 28)) == 0) {
+ writeVarint32FourBytes(value);
+ } else {
+ writeVarint32FiveBytes(value);
+ }
+ }
+
+ private void writeVarint32OneByte(int value) {
+ buffer.put(pos--, (byte) value);
+ }
+
+ private void writeVarint32TwoBytes(int value) {
+ // Byte order is little-endian.
+ pos -= 2;
+ buffer.putShort(pos + 1, (short) (((value & (0x7F << 7)) << 1) | ((value & 0x7F) | 0x80)));
+ }
+
+ private void writeVarint32ThreeBytes(int value) {
+ // Byte order is little-endian.
+ pos -= 3;
+ buffer.putInt(
+ pos,
+ ((value & (0x7F << 14)) << 10)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 9)
+ | ((value & 0x7F) | 0x80) << 8);
+ }
+
+ private void writeVarint32FourBytes(int value) {
+ // Byte order is little-endian.
+ pos -= 4;
+ buffer.putInt(
+ pos + 1,
+ ((value & (0x7F << 21)) << 3)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
+ | ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32FiveBytes(int value) {
+ // Byte order is little-endian.
+ buffer.put(pos--, (byte) (value >>> 28));
+ pos -= 4;
+ buffer.putInt(
+ pos + 1,
+ ((((value >>> 21) & 0x7F) | 0x80) << 24)
+ | ((((value >>> 14) & 0x7F) | 0x80) << 16)
+ | ((((value >>> 7) & 0x7F) | 0x80) << 8)
+ | ((value & 0x7F) | 0x80));
+ }
+
+ @Override
+ void writeVarint64(long value) {
+ switch (computeUInt64SizeNoTag(value)) {
+ case 1:
+ writeVarint64OneByte(value);
+ break;
+ case 2:
+ writeVarint64TwoBytes(value);
+ break;
+ case 3:
+ writeVarint64ThreeBytes(value);
+ break;
+ case 4:
+ writeVarint64FourBytes(value);
+ break;
+ case 5:
+ writeVarint64FiveBytes(value);
+ break;
+ case 6:
+ writeVarint64SixBytes(value);
+ break;
+ case 7:
+ writeVarint64SevenBytes(value);
+ break;
+ case 8:
+ writeVarint64EightBytes(value);
+ break;
+ case 9:
+ writeVarint64NineBytes(value);
+ break;
+ case 10:
+ writeVarint64TenBytes(value);
+ break;
+ }
+ }
+
+ private void writeVarint64OneByte(long value) {
+ writeVarint32OneByte((int) value);
+ }
+
+ private void writeVarint64TwoBytes(long value) {
+ writeVarint32TwoBytes((int) value);
+ }
+
+ private void writeVarint64ThreeBytes(long value) {
+ writeVarint32ThreeBytes((int) value);
+ }
+
+ private void writeVarint64FourBytes(long value) {
+ writeVarint32FourBytes((int) value);
+ }
+
+ private void writeVarint64FiveBytes(long value) {
+ // Byte order is little-endian.
+ pos -= 5;
+ buffer.putLong(
+ pos - 2,
+ ((value & (0x7FL << 28)) << 28)
+ | (((value & (0x7F << 21)) | (0x80 << 21)) << 27)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 26)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 25)
+ | (((value & 0x7F) | 0x80)) << 24);
+ }
+
+ private void writeVarint64SixBytes(long value) {
+ // Byte order is little-endian.
+ pos -= 6;
+ buffer.putLong(
+ pos - 1,
+ ((value & (0x7FL << 35)) << 21)
+ | (((value & (0x7FL << 28)) | (0x80L << 28)) << 20)
+ | (((value & (0x7F << 21)) | (0x80 << 21)) << 19)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 18)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 17)
+ | (((value & 0x7F) | 0x80)) << 16);
+ }
+
+ private void writeVarint64SevenBytes(long value) {
+ // Byte order is little-endian.
+ pos -= 7;
+ buffer.putLong(
+ pos,
+ ((value & (0x7FL << 42)) << 14)
+ | (((value & (0x7FL << 35)) | (0x80L << 35)) << 13)
+ | (((value & (0x7FL << 28)) | (0x80L << 28)) << 12)
+ | (((value & (0x7F << 21)) | (0x80 << 21)) << 11)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 10)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 9)
+ | (((value & 0x7F) | 0x80)) << 8);
+ }
+
+ private void writeVarint64EightBytes(long value) {
+ // Byte order is little-endian.
+ pos -= 8;
+ buffer.putLong(
+ pos + 1,
+ ((value & (0x7FL << 49)) << 7)
+ | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6)
+ | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5)
+ | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4)
+ | (((value & (0x7F << 21)) | (0x80 << 21)) << 3)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
+ | ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64EightBytesWithSign(long value) {
+ // Byte order is little-endian.
+ pos -= 8;
+ buffer.putLong(
+ pos + 1,
+ (((value & (0x7FL << 49)) | (0x80L << 49)) << 7)
+ | (((value & (0x7FL << 42)) | (0x80L << 42)) << 6)
+ | (((value & (0x7FL << 35)) | (0x80L << 35)) << 5)
+ | (((value & (0x7FL << 28)) | (0x80L << 28)) << 4)
+ | (((value & (0x7F << 21)) | (0x80 << 21)) << 3)
+ | (((value & (0x7F << 14)) | (0x80 << 14)) << 2)
+ | (((value & (0x7F << 7)) | (0x80 << 7)) << 1)
+ | ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64NineBytes(long value) {
+ buffer.put(pos--, (byte) (value >>> 56));
+ writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL);
+ }
+
+ private void writeVarint64TenBytes(long value) {
+ buffer.put(pos--, (byte) (value >>> 63));
+ buffer.put(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
+ writeVarint64EightBytesWithSign(value & 0xFFFFFFFFFFFFFFL);
+ }
+
+ @Override
+ void writeFixed32(int value) {
+ pos -= 4;
+ buffer.putInt(pos + 1, value);
+ }
+
+ @Override
+ void writeFixed64(long value) {
+ pos -= 8;
+ buffer.putLong(pos + 1, value);
+ }
+
+ @Override
+ void writeString(String in) {
+ // Request enough space to write the ASCII string.
+ requireSpace(in.length());
+
+ // We know the buffer is big enough...
+ int i = in.length() - 1;
+ pos -= i;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
+ buffer.put(pos + i, (byte) c);
+ }
+ if (i == -1) {
+ // Move the position past the ASCII string.
+ pos -= 1;
+ return;
+ }
+ pos += i;
+ for (char c; i >= 0; i--) {
+ c = in.charAt(i);
+ if (c < 0x80 && pos >= 0) {
+ buffer.put(pos--, (byte) c);
+ } else if (c < 0x800 && pos > 0) { // 11 bits, two UTF-8 bytes
+ buffer.put(pos--, (byte) (0x80 | (0x3F & c)));
+ buffer.put(pos--, (byte) ((0xF << 6) | (c >>> 6)));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && pos > 1) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ buffer.put(pos--, (byte) (0x80 | (0x3F & c)));
+ buffer.put(pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
+ buffer.put(pos--, (byte) ((0xF << 5) | (c >>> 12)));
+ } else if (pos > 2) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+ // four UTF-8 bytes
+ char high = 0;
+ if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
+ throw new Utf8.UnpairedSurrogateException(i - 1, i);
+ }
+ i--;
+ int codePoint = Character.toCodePoint(high, c);
+ buffer.put(pos--, (byte) (0x80 | (0x3F & codePoint)));
+ buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ buffer.put(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ buffer.put(pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ } else {
+ // Buffer is full - allocate a new one and revisit the current character.
+ requireSpace(i);
+ i++;
+ }
+ }
+ }
+
+ @Override
+ public void write(byte value) {
+ buffer.put(pos--, value);
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ buffer.position(pos + 1);
+ buffer.put(value, offset, length);
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ buffer.position(pos + 1);
+ buffer.put(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ buffer.position(pos + 1);
+ buffer.put(value);
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ buffer.position(pos + 1);
+ buffer.put(value);
+ }
+
+ @Override
+ void requireSpace(int size) {
+ if (spaceLeft() < size) {
+ nextBuffer(size);
+ }
+ }
+ }
+
+ /** Writer that uses unsafe operations on a target {@link ByteBuffer}. */
+ private static final class UnsafeDirectWriter extends BinaryWriter {
+ private ByteBuffer buffer;
+ private long bufferOffset;
+ private long limitMinusOne;
+ private long pos;
+
+ UnsafeDirectWriter(BufferAllocator alloc, int chunkSize) {
+ super(alloc, chunkSize);
+ nextBuffer();
+ }
+
+ /** Indicates whether the required unsafe operations are supported on this platform. */
+ private static boolean isSupported() {
+ return UnsafeUtil.hasUnsafeByteBufferOperations();
+ }
+
+ private void nextBuffer() {
+ nextBuffer(newDirectBuffer());
+ }
+
+ private void nextBuffer(int capacity) {
+ nextBuffer(newDirectBuffer(capacity));
+ }
+
+ private void nextBuffer(AllocatedBuffer allocatedBuffer) {
+ if (!allocatedBuffer.hasNioBuffer()) {
+ throw new RuntimeException("Allocated buffer does not have NIO buffer");
+ }
+ ByteBuffer nioBuffer = allocatedBuffer.nioBuffer();
+ if (!nioBuffer.isDirect()) {
+ throw new RuntimeException("Allocator returned non-direct buffer");
+ }
+
+ finishCurrentBuffer();
+ buffers.addFirst(allocatedBuffer);
+
+ buffer = nioBuffer;
+ buffer.limit(buffer.capacity());
+ buffer.position(0);
+
+ bufferOffset = UnsafeUtil.addressOffset(buffer);
+ limitMinusOne = bufferOffset + (buffer.limit() - 1);
+ pos = limitMinusOne;
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return totalDoneBytes + bytesWrittenToCurrentBuffer();
+ }
+
+ private int bytesWrittenToCurrentBuffer() {
+ return (int) (limitMinusOne - pos);
+ }
+
+ private int spaceLeft() {
+ return bufferPos() + 1;
+ }
+
+ @Override
+ void finishCurrentBuffer() {
+ if (buffer != null) {
+ totalDoneBytes += bytesWrittenToCurrentBuffer();
+ // Update the indices on the netty buffer.
+ buffer.position(bufferPos() + 1);
+ buffer = null;
+ pos = 0;
+ limitMinusOne = 0;
+ }
+ }
+
+ private int bufferPos() {
+ return (int) (pos - bufferOffset);
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeSInt32(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED32_SIZE);
+ writeFixed32(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED32);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeVarint64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeSInt64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + MAX_VARINT64_SIZE);
+ writeSInt64(value);
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) {
+ requireSpace(MAX_VARINT32_SIZE + FIXED64_SIZE);
+ writeFixed64(value);
+ writeTag(fieldNumber, WIRETYPE_FIXED64);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) {
+ requireSpace(MAX_VARINT32_SIZE + 1);
+ write((byte) (value ? 1 : 0));
+ writeTag(fieldNumber, WIRETYPE_VARINT);
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) {
+ int prevBytes = getTotalBytesWritten();
+ writeString(value);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(2 * MAX_VARINT32_SIZE);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) {
+ try {
+ value.writeToReverse(this);
+ } catch (IOException e) {
+ // Should never happen since the writer does not throw.
+ throw new RuntimeException(e);
+ }
+
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(value.size());
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ Protobuf.getInstance().writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
+ int prevBytes = getTotalBytesWritten();
+ schema.writeTo(value, this);
+ int length = getTotalBytesWritten() - prevBytes;
+ requireSpace(MAX_VARINT32_SIZE * 2);
+ writeVarint32(length);
+ writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ Protobuf.getInstance().writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ schema.writeTo(value, this);
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeStartGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeEndGroup(int fieldNumber) {
+ writeTag(fieldNumber, WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ void writeInt32(int value) {
+ if (value >= 0) {
+ writeVarint32(value);
+ } else {
+ writeVarint64(value);
+ }
+ }
+
+ @Override
+ void writeSInt32(int value) {
+ writeVarint32(CodedOutputStream.encodeZigZag32(value));
+ }
+
+ @Override
+ void writeSInt64(long value) {
+ writeVarint64(CodedOutputStream.encodeZigZag64(value));
+ }
+
+ @Override
+ void writeBool(boolean value) {
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ void writeTag(int fieldNumber, int wireType) {
+ writeVarint32(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ void writeVarint32(int value) {
+ if ((value & (~0 << 7)) == 0) {
+ writeVarint32OneByte(value);
+ } else if ((value & (~0 << 14)) == 0) {
+ writeVarint32TwoBytes(value);
+ } else if ((value & (~0 << 21)) == 0) {
+ writeVarint32ThreeBytes(value);
+ } else if ((value & (~0 << 28)) == 0) {
+ writeVarint32FourBytes(value);
+ } else {
+ writeVarint32FiveBytes(value);
+ }
+ }
+
+ private void writeVarint32OneByte(int value) {
+ UnsafeUtil.putByte(pos--, (byte) value);
+ }
+
+ private void writeVarint32TwoBytes(int value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 7));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32ThreeBytes(int value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 14));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32FourBytes(int value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 21));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint32FiveBytes(int value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 28));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ @Override
+ void writeVarint64(long value) {
+ switch (computeUInt64SizeNoTag(value)) {
+ case 1:
+ writeVarint64OneByte(value);
+ break;
+ case 2:
+ writeVarint64TwoBytes(value);
+ break;
+ case 3:
+ writeVarint64ThreeBytes(value);
+ break;
+ case 4:
+ writeVarint64FourBytes(value);
+ break;
+ case 5:
+ writeVarint64FiveBytes(value);
+ break;
+ case 6:
+ writeVarint64SixBytes(value);
+ break;
+ case 7:
+ writeVarint64SevenBytes(value);
+ break;
+ case 8:
+ writeVarint64EightBytes(value);
+ break;
+ case 9:
+ writeVarint64NineBytes(value);
+ break;
+ case 10:
+ writeVarint64TenBytes(value);
+ break;
+ }
+ }
+
+ private void writeVarint64OneByte(long value) {
+ UnsafeUtil.putByte(pos--, (byte) value);
+ }
+
+ private void writeVarint64TwoBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 7));
+ UnsafeUtil.putByte(pos--, (byte) (((int) value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64ThreeBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (((int) value) >>> 14));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64FourBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 21));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64FiveBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 28));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64SixBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 35));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64SevenBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 42));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64EightBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 49));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64NineBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 56));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ private void writeVarint64TenBytes(long value) {
+ UnsafeUtil.putByte(pos--, (byte) (value >>> 63));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 56) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 49) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 42) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 35) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 28) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 21) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 14) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) (((value >>> 7) & 0x7F) | 0x80));
+ UnsafeUtil.putByte(pos--, (byte) ((value & 0x7F) | 0x80));
+ }
+
+ @Override
+ void writeFixed32(int value) {
+ UnsafeUtil.putByte(pos--, (byte) ((value >> 24) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((value >> 16) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((value >> 8) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) (value & 0xFF));
+ }
+
+ @Override
+ void writeFixed64(long value) {
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 56) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 48) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 40) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 32) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 24) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 16) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value >> 8) & 0xFF));
+ UnsafeUtil.putByte(pos--, (byte) ((int) (value) & 0xFF));
+ }
+
+ @Override
+ void writeString(String in) {
+ // Request enough space to write the ASCII string.
+ requireSpace(in.length());
+
+ // We know the buffer is big enough...
+ int i = in.length() - 1;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i >= 0 && (c = in.charAt(i)) < 0x80; i--) {
+ UnsafeUtil.putByte(pos--, (byte) c);
+ }
+ if (i == -1) {
+ // ASCII.
+ return;
+ }
+ for (char c; i >= 0; i--) {
+ c = in.charAt(i);
+ if (c < 0x80 && pos >= bufferOffset) {
+ UnsafeUtil.putByte(pos--, (byte) c);
+ } else if (c < 0x800 && pos > bufferOffset) { // 11 bits, two UTF-8 bytes
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c)));
+ UnsafeUtil.putByte(pos--, (byte) ((0xF << 6) | (c >>> 6)));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c)
+ && pos > bufferOffset + 1) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & c)));
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (c >>> 6))));
+ UnsafeUtil.putByte(pos--, (byte) ((0xF << 5) | (c >>> 12)));
+ } else if (pos > bufferOffset + 2) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
+ // four UTF-8 bytes
+ final char high;
+ if (i == 0 || !Character.isSurrogatePair(high = in.charAt(i - 1), c)) {
+ throw new Utf8.UnpairedSurrogateException(i - 1, i);
+ }
+ i--;
+ int codePoint = Character.toCodePoint(high, c);
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & codePoint)));
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ UnsafeUtil.putByte(pos--, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ UnsafeUtil.putByte(pos--, (byte) ((0xF << 4) | (codePoint >>> 18)));
+ } else {
+ // Buffer is full - allocate a new one and revisit the current character.
+ requireSpace(i);
+ i++;
+ }
+ }
+ }
+
+ @Override
+ public void write(byte value) {
+ UnsafeUtil.putByte(pos--, value);
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ buffer.position(bufferPos() + 1);
+ buffer.put(value, offset, length);
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) {
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value, offset, length));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ buffer.position(bufferPos() + 1);
+ buffer.put(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ nextBuffer(length);
+ }
+
+ pos -= length;
+ buffer.position(bufferPos() + 1);
+ buffer.put(value);
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) {
+ int length = value.remaining();
+ if (spaceLeft() < length) {
+ // We consider the value to be immutable (likely the internals of a ByteString). Just
+ // wrap it in a Netty buffer and add it to the output buffer.
+ totalDoneBytes += length;
+ buffers.addFirst(AllocatedBuffer.wrap(value));
+
+ // Advance the writer to the next buffer.
+ // TODO(nathanmittler): Consider slicing if space available above some threshold.
+ nextBuffer();
+ return;
+ }
+
+ pos -= length;
+ buffer.position(bufferPos() + 1);
+ buffer.put(value);
+ }
+
+ @Override
+ void requireSpace(int size) {
+ if (spaceLeft() < size) {
+ nextBuffer(size);
+ }
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/BufferAllocator.java b/java/core/src/main/java/com/google/protobuf/BufferAllocator.java
new file mode 100755
index 000000000..bfd9c7237
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/BufferAllocator.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;
+
+import java.nio.ByteBuffer;
+
+/**
+ * An object responsible for allocation of buffers. This is an extension point to enable buffer
+ * pooling within an application.
+ */
+@ExperimentalApi
+abstract class BufferAllocator {
+ private static final BufferAllocator UNPOOLED =
+ new BufferAllocator() {
+ @Override
+ public AllocatedBuffer allocateHeapBuffer(int capacity) {
+ return AllocatedBuffer.wrap(new byte[capacity]);
+ }
+
+ @Override
+ public AllocatedBuffer allocateDirectBuffer(int capacity) {
+ return AllocatedBuffer.wrap(ByteBuffer.allocateDirect(capacity));
+ }
+ };
+
+ /** Returns an unpooled buffer allocator, which will create a new buffer for each request. */
+ public static BufferAllocator unpooled() {
+ return UNPOOLED;
+ }
+
+ /** Allocates a buffer with the given capacity that is backed by an array on the heap. */
+ public abstract AllocatedBuffer allocateHeapBuffer(int capacity);
+
+ /** Allocates a direct (i.e. non-heap) buffer with the given capacity. */
+ public abstract AllocatedBuffer allocateDirectBuffer(int capacity);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java
index 648991dc2..e5454a63d 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -732,6 +732,16 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
*/
abstract void writeTo(ByteOutput byteOutput) throws IOException;
+ /**
+ * This method behaves exactly the same as {@link #writeTo(ByteOutput)} unless the {@link
+ * ByteString} is a rope. For ropes, the leaf nodes are written in reverse order to the {@code
+ * byteOutput}.
+ *
+ * @param byteOutput the output target to receive the bytes
+ * @throws IOException if an I/O error occurs
+ * @see UnsafeByteOperations#unsafeWriteToReverse(ByteString, ByteOutput)
+ */
+ abstract void writeToReverse(ByteOutput byteOutput) throws IOException;
/**
* Constructs a read-only {@code java.nio.ByteBuffer} whose content is equal to the contents of
@@ -862,6 +872,10 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
return true;
}
+ @Override
+ void writeToReverse(ByteOutput byteOutput) throws IOException {
+ writeTo(byteOutput);
+ }
/**
* Check equality of the substring of given length of this object starting at zero with another
@@ -1438,14 +1452,16 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
LiteralByteString lbsOther = (LiteralByteString) other;
byte[] thisBytes = bytes;
byte[] otherBytes = lbsOther.bytes;
-
- return UnsafeUtil.mismatch(
- thisBytes,
- getOffsetIntoBytes(),
- otherBytes,
- lbsOther.getOffsetIntoBytes() + offset,
- length)
- == -1;
+ 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));
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index 6cece058e..87c683725 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -72,6 +72,9 @@ public abstract class CodedInputStream {
/** Visible for subclasses. See setSizeLimit() */
int sizeLimit = DEFAULT_SIZE_LIMIT;
+ /** Used to adapt to the experimental {@link Reader} interface. */
+ CodedInputStreamReader wrapper;
+
/** Create a new CodedInputStream wrapping the given InputStream. */
public static CodedInputStream newInstance(final InputStream input) {
return newInstance(input, DEFAULT_BUFFER_SIZE);
@@ -2263,7 +2266,7 @@ public abstract class CodedInputStream {
return result;
}
// Slow path: Build a byte array first then copy it.
- return new String(readRawBytesSlowPath(size), UTF_8);
+ return new String(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false), UTF_8);
}
@Override
@@ -2287,7 +2290,7 @@ public abstract class CodedInputStream {
pos = tempPos + size;
} else {
// Slow path: Build a byte array first then copy it.
- bytes = readRawBytesSlowPath(size);
+ bytes = readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
tempPos = 0;
}
return Utf8.decodeUtf8(bytes, tempPos, size);
@@ -2392,7 +2395,8 @@ public abstract class CodedInputStream {
return result;
} else {
// Slow path: Build a byte array first then copy it.
- return readRawBytesSlowPath(size);
+ // TODO(dweis): Do we want to protect from malicious input streams here?
+ return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
}
}
@@ -2409,7 +2413,10 @@ public abstract class CodedInputStream {
return Internal.EMPTY_BYTE_BUFFER;
}
// Slow path: Build a byte array first then copy it.
- return ByteBuffer.wrap(readRawBytesSlowPath(size));
+
+ // We must copy as the byte array was handed off to the InputStream and a malicious
+ // implementation could retain a reference.
+ return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true));
}
@Override
@@ -2812,19 +2819,24 @@ public abstract class CodedInputStream {
pos = tempPos + size;
return Arrays.copyOfRange(buffer, tempPos, tempPos + size);
} else {
- return readRawBytesSlowPath(size);
+ // TODO(dweis): Do we want to protect from malicious input streams here?
+ return readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ false);
}
}
/**
* Exactly like readRawBytes, but caller must have already checked the fast path: (size <=
* (bufferSize - pos) && size > 0)
+ *
+ * If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to
+ * untrusted code.
*/
- private byte[] readRawBytesSlowPath(final int size) throws IOException {
+ private byte[] readRawBytesSlowPath(
+ final int size, boolean ensureNoLeakedReferences) throws IOException {
// Attempt to read the data in one byte array when it's safe to do.
byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
- return result;
+ return ensureNoLeakedReferences ? result.clone() : result;
}
final int originalBufferPos = pos;
@@ -2862,6 +2874,8 @@ public abstract class CodedInputStream {
/**
* Attempts to read the data in one byte array when it's safe to do. Returns null if the size to
* read is too large and needs to be allocated in smaller chunks for security reasons.
+ *
+ * Returns a byte[] that may have escaped to user code via InputStream APIs.
*/
private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
if (size == 0) {
@@ -2916,7 +2930,11 @@ public abstract class CodedInputStream {
return null;
}
- /** Reads the remaining data in small chunks from the input stream. */
+ /**
+ * Reads the remaining data in small chunks from the input stream.
+ *
+ * Returns a byte[] that may have escaped to user code via InputStream APIs.
+ */
private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
// 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
@@ -2953,7 +2971,9 @@ public abstract class CodedInputStream {
private ByteString readBytesSlowPath(final int size) throws IOException {
final byte[] result = readRawBytesSlowPathOneChunk(size);
if (result != null) {
- return ByteString.wrap(result);
+ // We must copy as the byte array was handed off to the InputStream and a malicious
+ // implementation could retain a reference.
+ return ByteString.copyFrom(result);
}
final int originalBufferPos = pos;
@@ -2971,13 +2991,20 @@ public abstract class CodedInputStream {
// chunks.
List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
- // Wrap the byte arrays into a single ByteString.
- List<ByteString> byteStrings = new ArrayList<ByteString>(1 + chunks.size());
- byteStrings.add(ByteString.copyFrom(buffer, originalBufferPos, bufferedBytes));
- for (byte[] chunk : chunks) {
- byteStrings.add(ByteString.wrap(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;
}
- return ByteString.copyFrom(byteStrings);
+
+ return ByteString.wrap(bytes);
}
@Override
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java
new file mode 100755
index 000000000..7658f629d
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java
@@ -0,0 +1,1333 @@
+// 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.FIXED32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED64_SIZE;
+import static com.google.protobuf.WireFormat.WIRETYPE_END_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED32;
+import static com.google.protobuf.WireFormat.WIRETYPE_FIXED64;
+import static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
+import static com.google.protobuf.WireFormat.WIRETYPE_START_GROUP;
+import static com.google.protobuf.WireFormat.WIRETYPE_VARINT;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/** An adapter between the {@link Reader} interface and {@link CodedInputStream}. */
+@ExperimentalApi
+final class CodedInputStreamReader implements Reader {
+ private static final int FIXED32_MULTIPLE_MASK = FIXED32_SIZE - 1;
+ private static final int FIXED64_MULTIPLE_MASK = FIXED64_SIZE - 1;
+ private static final int NEXT_TAG_UNSET = 0;
+
+ private final CodedInputStream input;
+ private int tag;
+ private int endGroupTag;
+ private int nextTag = NEXT_TAG_UNSET;
+
+ public static CodedInputStreamReader forCodedInput(CodedInputStream input) {
+ if (input.wrapper != null) {
+ return input.wrapper;
+ }
+ return new CodedInputStreamReader(input);
+ }
+
+ private CodedInputStreamReader(CodedInputStream input) {
+ this.input = Internal.checkNotNull(input, "input");
+ this.input.wrapper = this;
+ }
+
+ @Override
+ public boolean shouldDiscardUnknownFields() {
+ return input.shouldDiscardUnknownFields();
+ }
+
+ @Override
+ public int getFieldNumber() throws IOException {
+ if (nextTag != NEXT_TAG_UNSET) {
+ tag = nextTag;
+ nextTag = NEXT_TAG_UNSET;
+ } else {
+ tag = input.readTag();
+ }
+ if (tag == 0 || tag == endGroupTag) {
+ return Reader.READ_DONE;
+ }
+ return WireFormat.getTagFieldNumber(tag);
+ }
+
+ @Override
+ public int getTag() {
+ return tag;
+ }
+
+ @Override
+ public boolean skipField() throws IOException {
+ if (input.isAtEnd() || tag == endGroupTag) {
+ return false;
+ }
+ return input.skipField(tag);
+ }
+
+ private void requireWireType(int requiredWireType) throws IOException {
+ if (WireFormat.getTagWireType(tag) != requiredWireType) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return input.readDouble();
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return input.readFloat();
+ }
+
+ @Override
+ public long readUInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readUInt64();
+ }
+
+ @Override
+ public long readInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readInt64();
+ }
+
+ @Override
+ public int readInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readInt32();
+ }
+
+ @Override
+ public long readFixed64() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return input.readFixed64();
+ }
+
+ @Override
+ public int readFixed32() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return input.readFixed32();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readBool();
+ }
+
+ @Override
+ public String readString() throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return input.readString();
+ }
+
+ @Override
+ public String readStringRequireUtf8() throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return input.readStringRequireUtf8();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return readMessage(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T readMessageBySchemaWithCheck(
+ Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return readMessage(schema, extensionRegistry);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_START_GROUP);
+ return readGroup(Protobuf.getInstance().schemaFor(clazz), extensionRegistry);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_START_GROUP);
+ return readGroup(schema, extensionRegistry);
+ }
+
+ // Should have the same semantics of CodedInputStream#readMessage()
+ private <T> T readMessage(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int size = input.readUInt32();
+ if (input.recursionDepth >= input.recursionLimit) {
+ throw InvalidProtocolBufferException.recursionLimitExceeded();
+ }
+
+ // Push the new limit.
+ final int prevLimit = input.pushLimit(size);
+ // Allocate and read the message.
+ T message = schema.newInstance();
+ ++input.recursionDepth;
+ schema.mergeFrom(message, this, extensionRegistry);
+ schema.makeImmutable(message);
+ input.checkLastTagWas(0);
+ --input.recursionDepth;
+ // Restore the previous limit.
+ input.popLimit(prevLimit);
+ return message;
+ }
+
+ private <T> T readGroup(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ int prevEndGroupTag = endGroupTag;
+ endGroupTag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), WIRETYPE_END_GROUP);
+
+ try {
+ // Allocate and read the message.
+ T message = schema.newInstance();
+ schema.mergeFrom(message, this, extensionRegistry);
+ schema.makeImmutable(message);
+
+ if (tag != endGroupTag) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ return message;
+ } finally {
+ // Restore the old end group tag.
+ endGroupTag = prevEndGroupTag;
+ }
+ }
+
+ @Override
+ public ByteString readBytes() throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ return input.readBytes();
+ }
+
+ @Override
+ public int readUInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readUInt32();
+ }
+
+ @Override
+ public int readEnum() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readEnum();
+ }
+
+ @Override
+ public int readSFixed32() throws IOException {
+ requireWireType(WIRETYPE_FIXED32);
+ return input.readSFixed32();
+ }
+
+ @Override
+ public long readSFixed64() throws IOException {
+ requireWireType(WIRETYPE_FIXED64);
+ return input.readSFixed64();
+ }
+
+ @Override
+ public int readSInt32() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readSInt32();
+ }
+
+ @Override
+ public long readSInt64() throws IOException {
+ requireWireType(WIRETYPE_VARINT);
+ return input.readSInt64();
+ }
+
+ @Override
+ public void readDoubleList(List<Double> target) throws IOException {
+ if (target instanceof DoubleArrayList) {
+ DoubleArrayList plist = (DoubleArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addDouble(input.readDouble());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addDouble(input.readDouble());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readDouble());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(input.readDouble());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFloatList(List<Float> target) throws IOException {
+ if (target instanceof FloatArrayList) {
+ FloatArrayList plist = (FloatArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addFloat(input.readFloat());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addFloat(input.readFloat());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readFloat());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(input.readFloat());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readUInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addLong(input.readUInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(input.readUInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readUInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readUInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addLong(input.readInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(input.readInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(input.readInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFixed64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addLong(input.readFixed64());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addLong(input.readFixed64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readFixed64());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(input.readFixed64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readFixed32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readFixed32());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addInt(input.readFixed32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readFixed32());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(input.readFixed32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readBoolList(List<Boolean> target) throws IOException {
+ if (target instanceof BooleanArrayList) {
+ BooleanArrayList plist = (BooleanArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addBoolean(input.readBool());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addBoolean(input.readBool());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readBool());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readBool());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readStringList(List<String> target) throws IOException {
+ readStringListInternal(target, false);
+ }
+
+ @Override
+ public void readStringListRequireUtf8(List<String> target) throws IOException {
+ readStringListInternal(target, true);
+ }
+
+ public void readStringListInternal(List<String> target, boolean requireUtf8) throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+
+ if (target instanceof LazyStringList && !requireUtf8) {
+ LazyStringList lazyList = (LazyStringList) target;
+ while (true) {
+ lazyList.add(readBytes());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ } else {
+ while (true) {
+ target.add(requireUtf8 ? readStringRequireUtf8() : readString());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public <T> void readMessageList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
+ readMessageList(target, schema, extensionRegistry);
+ }
+
+ @Override
+ public <T> void readMessageList(
+ List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ final int listTag = tag;
+ while (true) {
+ target.add(readMessage(schema, extensionRegistry));
+ if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != listTag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public <T> void readGroupList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ final Schema<T> schema = Protobuf.getInstance().schemaFor(targetType);
+ readGroupList(target, schema, extensionRegistry);
+ }
+
+ @Override
+ public <T> void readGroupList(
+ List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_START_GROUP) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ final int listTag = tag;
+ while (true) {
+ target.add(readGroup(schema, extensionRegistry));
+ if (input.isAtEnd() || nextTag != NEXT_TAG_UNSET) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != listTag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void readBytesList(List<ByteString> target) throws IOException {
+ if (WireFormat.getTagWireType(tag) != WIRETYPE_LENGTH_DELIMITED) {
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+
+ while (true) {
+ target.add(readBytes());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ }
+
+ @Override
+ public void readUInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readUInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(input.readUInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readUInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readUInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readEnumList(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readEnum());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(input.readEnum());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readEnum());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readEnum());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSFixed32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readSFixed32());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ plist.addInt(input.readSFixed32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed32Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readSFixed32());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED32:
+ while (true) {
+ target.add(input.readSFixed32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSFixed64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addLong(input.readSFixed64());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ plist.addLong(input.readSFixed64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ verifyPackedFixed64Length(bytes);
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readSFixed64());
+ } while (input.getTotalBytesRead() < endPos);
+ break;
+ case WIRETYPE_FIXED64:
+ while (true) {
+ target.add(input.readSFixed64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSInt32List(List<Integer> target) throws IOException {
+ if (target instanceof IntArrayList) {
+ IntArrayList plist = (IntArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addInt(input.readSInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addInt(input.readSInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readSInt32());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readSInt32());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ @Override
+ public void readSInt64List(List<Long> target) throws IOException {
+ if (target instanceof LongArrayList) {
+ LongArrayList plist = (LongArrayList) target;
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ plist.addLong(input.readSInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ plist.addLong(input.readSInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ } else {
+ switch (WireFormat.getTagWireType(tag)) {
+ case WIRETYPE_LENGTH_DELIMITED:
+ final int bytes = input.readUInt32();
+ int endPos = input.getTotalBytesRead() + bytes;
+ do {
+ target.add(input.readSInt64());
+ } while (input.getTotalBytesRead() < endPos);
+ requirePosition(endPos);
+ break;
+ case WIRETYPE_VARINT:
+ while (true) {
+ target.add(input.readSInt64());
+ if (input.isAtEnd()) {
+ return;
+ }
+ int nextTag = input.readTag();
+ if (nextTag != tag) {
+ // We've reached the end of the repeated field. Save the next tag value.
+ this.nextTag = nextTag;
+ return;
+ }
+ }
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+ }
+
+ private void verifyPackedFixed64Length(int bytes) throws IOException {
+ if ((bytes & FIXED64_MULTIPLE_MASK) != 0) {
+ // Require that the number of bytes be a multiple of 8.
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <K, V> void readMap(
+ Map<K, V> target,
+ MapEntryLite.Metadata<K, V> metadata,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ requireWireType(WIRETYPE_LENGTH_DELIMITED);
+ int size = input.readUInt32();
+ final int prevLimit = input.pushLimit(size);
+ K key = metadata.defaultKey;
+ V value = metadata.defaultValue;
+ try {
+ while (true) {
+ int number = getFieldNumber();
+ if (number == READ_DONE || input.isAtEnd()) {
+ break;
+ }
+ try {
+ switch (number) {
+ case 1:
+ key = (K) readField(metadata.keyType, null, null);
+ break;
+ case 2:
+ value =
+ (V)
+ readField(
+ metadata.valueType, metadata.defaultValue.getClass(), extensionRegistry);
+ break;
+ default:
+ if (!skipField()) {
+ throw new InvalidProtocolBufferException("Unable to parse map entry.");
+ }
+ break;
+ }
+ } catch (InvalidProtocolBufferException.InvalidWireTypeException ignore) {
+ // the type doesn't match, skip the field.
+ if (!skipField()) {
+ throw new InvalidProtocolBufferException("Unable to parse map entry.");
+ }
+ }
+ }
+ target.put(key, value);
+ } finally {
+ // Restore the previous limit.
+ input.popLimit(prevLimit);
+ }
+ }
+
+ private Object readField(
+ WireFormat.FieldType fieldType, Class<?> messageType, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ switch (fieldType) {
+ case BOOL:
+ return readBool();
+ case BYTES:
+ return readBytes();
+ case DOUBLE:
+ return readDouble();
+ case ENUM:
+ return readEnum();
+ case FIXED32:
+ return readFixed32();
+ case FIXED64:
+ return readFixed64();
+ case FLOAT:
+ return readFloat();
+ case INT32:
+ return readInt32();
+ case INT64:
+ return readInt64();
+ case MESSAGE:
+ return readMessage(messageType, extensionRegistry);
+ case SFIXED32:
+ return readSFixed32();
+ case SFIXED64:
+ return readSFixed64();
+ case SINT32:
+ return readSInt32();
+ case SINT64:
+ return readSInt64();
+ case STRING:
+ return readStringRequireUtf8();
+ case UINT32:
+ return readUInt32();
+ case UINT64:
+ return readUInt64();
+ default:
+ throw new RuntimeException("unsupported field type.");
+ }
+ }
+
+ private void verifyPackedFixed32Length(int bytes) throws IOException {
+ if ((bytes & FIXED32_MULTIPLE_MASK) != 0) {
+ // Require that the number of bytes be a multiple of 4.
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+
+ private void requirePosition(int expectedPosition) throws IOException {
+ if (input.getTotalBytesRead() != expectedPosition) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
index 3823f81fc..a9192d33e 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -60,6 +60,9 @@ 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();
+ /** Used to adapt to the experimental {@link Writer} interface. */
+ CodedOutputStreamWriter wrapper;
+
/** @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. */
@Deprecated public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE;
@@ -361,6 +364,10 @@ public abstract class CodedOutputStream extends ByteOutput {
public abstract void writeMessage(final int fieldNumber, final MessageLite value)
throws IOException;
+ /** Write an embedded message field, including tag, to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ abstract void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException;
/**
* Write a MessageSet extension field to the stream. For historical reasons, the wire format
@@ -466,6 +473,9 @@ public abstract class CodedOutputStream extends ByteOutput {
// Abstract to avoid overhead of additional virtual method calls.
public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
+ /** Write an embedded message field to the stream. */
+ // Abstract to avoid overhead of additional virtual method calls.
+ abstract void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException;
// =================================================================
@@ -651,6 +661,14 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value);
}
+ /**
+ * Compute the number of bytes that would be needed to encode an embedded message field, including
+ * tag.
+ */
+ static int computeMessageSize(
+ final int fieldNumber, final MessageLite value, final Schema schema) {
+ return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value, schema);
+ }
/**
* Compute the number of bytes that would be needed to encode a MessageSet extension to the
@@ -859,6 +877,10 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
+ /** Compute the number of bytes that would be needed to encode an embedded message field. */
+ static int computeMessageSizeNoTag(final MessageLite value, final Schema schema) {
+ return computeLengthDelimitedFieldSize(((AbstractMessageLite) value).getSerializedSize(schema));
+ }
static int computeLengthDelimitedFieldSize(int fieldLength) {
return computeUInt32SizeNoTag(fieldLength) + fieldLength;
@@ -993,6 +1015,18 @@ public abstract class CodedOutputStream extends ByteOutput {
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
}
+ /**
+ * Write a {@code group} field, including tag, to the stream.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ final void writeGroup(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ writeGroupNoTag(value, schema);
+ writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ }
/**
* Write a {@code group} field to the stream.
@@ -1004,6 +1038,15 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ /**
+ * Write a {@code group} field to the stream.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ final void writeGroupNoTag(final MessageLite value, Schema schema) throws IOException {
+ schema.writeTo(value, wrapper);
+ }
/**
* Compute the number of bytes that would be needed to encode a {@code group} field, including
@@ -1016,6 +1059,16 @@ public abstract class CodedOutputStream extends ByteOutput {
return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value);
}
+ /**
+ * Compute the number of bytes that would be needed to encode a {@code group} field, including
+ * tag.
+ *
+ * @deprecated groups are deprecated.
+ */
+ @Deprecated
+ static int computeGroupSize(final int fieldNumber, final MessageLite value, Schema schema) {
+ return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value, schema);
+ }
/** Compute the number of bytes that would be needed to encode a {@code group} field. */
@Deprecated
@@ -1023,6 +1076,11 @@ public abstract class CodedOutputStream extends ByteOutput {
return value.getSerializedSize();
}
+ /** Compute the number of bytes that would be needed to encode a {@code group} field. */
+ @Deprecated
+ static int computeGroupSizeNoTag(final MessageLite value, Schema schema) {
+ return ((AbstractMessageLite) value).getSerializedSize(schema);
+ }
/**
* Encode and write a varint. {@code value} is treated as unsigned, so it won't be sign-extended
@@ -1216,6 +1274,13 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
+ @Override
+ final void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
@@ -1241,6 +1306,11 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ @Override
+ final void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public final void write(byte value) throws IOException {
@@ -1571,6 +1641,12 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
+ @Override
+ void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value, schema);
+ }
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
@@ -1596,6 +1672,11 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ @Override
+ void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public void write(byte value) throws IOException {
@@ -1893,6 +1974,11 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
+ @Override
+ void writeMessage(int fieldNumber, MessageLite value, Schema schema) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value, schema);
+ }
@Override
public void writeMessageSetExtension(int fieldNumber, MessageLite value) throws IOException {
@@ -1916,6 +2002,11 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ @Override
+ void writeMessageNoTag(MessageLite value, Schema schema) throws IOException {
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public void write(byte value) throws IOException {
@@ -2419,6 +2510,12 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
+ @Override
+ void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value, schema);
+ }
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
@@ -2444,6 +2541,11 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ @Override
+ void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public void write(byte value) throws IOException {
@@ -2722,6 +2824,12 @@ public abstract class CodedOutputStream extends ByteOutput {
writeMessageNoTag(value);
}
+ @Override
+ void writeMessage(final int fieldNumber, final MessageLite value, Schema schema)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value, schema);
+ }
@Override
public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
@@ -2747,6 +2855,11 @@ public abstract class CodedOutputStream extends ByteOutput {
value.writeTo(this);
}
+ @Override
+ void writeMessageNoTag(final MessageLite value, Schema schema) throws IOException {
+ writeUInt32NoTag(((AbstractMessageLite) value).getSerializedSize(schema));
+ schema.writeTo(value, wrapper);
+ }
@Override
public void write(byte value) throws IOException {
diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java
new file mode 100755
index 000000000..0d1983cb0
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java
@@ -0,0 +1,691 @@
+// 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 static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/** An adapter between the {@link Writer} interface and {@link CodedOutputStream}. */
+@ExperimentalApi
+final class CodedOutputStreamWriter implements Writer {
+ private final CodedOutputStream output;
+
+ public static CodedOutputStreamWriter forCodedOutput(CodedOutputStream output) {
+ if (output.wrapper != null) {
+ return output.wrapper;
+ }
+ return new CodedOutputStreamWriter(output);
+ }
+
+ private CodedOutputStreamWriter(CodedOutputStream output) {
+ this.output = checkNotNull(output, "output");
+ this.output.wrapper = this;
+ }
+
+ @Override
+ public FieldOrder fieldOrder() {
+ return FieldOrder.ASCENDING;
+ }
+
+ public int getTotalBytesWritten() {
+ return output.getTotalBytesWritten();
+ }
+
+ @Override
+ public void writeSFixed32(int fieldNumber, int value) throws IOException {
+ output.writeSFixed32(fieldNumber, value);
+ }
+
+ @Override
+ public void writeInt64(int fieldNumber, long value) throws IOException {
+ output.writeInt64(fieldNumber, value);
+ }
+
+ @Override
+ public void writeSFixed64(int fieldNumber, long value) throws IOException {
+ output.writeSFixed64(fieldNumber, value);
+ }
+
+ @Override
+ public void writeFloat(int fieldNumber, float value) throws IOException {
+ output.writeFloat(fieldNumber, value);
+ }
+
+ @Override
+ public void writeDouble(int fieldNumber, double value) throws IOException {
+ output.writeDouble(fieldNumber, value);
+ }
+
+ @Override
+ public void writeEnum(int fieldNumber, int value) throws IOException {
+ output.writeEnum(fieldNumber, value);
+ }
+
+ @Override
+ public void writeUInt64(int fieldNumber, long value) throws IOException {
+ output.writeUInt64(fieldNumber, value);
+ }
+
+ @Override
+ public void writeInt32(int fieldNumber, int value) throws IOException {
+ output.writeInt32(fieldNumber, value);
+ }
+
+ @Override
+ public void writeFixed64(int fieldNumber, long value) throws IOException {
+ output.writeFixed64(fieldNumber, value);
+ }
+
+ @Override
+ public void writeFixed32(int fieldNumber, int value) throws IOException {
+ output.writeFixed32(fieldNumber, value);
+ }
+
+ @Override
+ public void writeBool(int fieldNumber, boolean value) throws IOException {
+ output.writeBool(fieldNumber, value);
+ }
+
+ @Override
+ public void writeString(int fieldNumber, String value) throws IOException {
+ output.writeString(fieldNumber, value);
+ }
+
+ @Override
+ public void writeBytes(int fieldNumber, ByteString value) throws IOException {
+ output.writeBytes(fieldNumber, value);
+ }
+
+ @Override
+ public void writeUInt32(int fieldNumber, int value) throws IOException {
+ output.writeUInt32(fieldNumber, value);
+ }
+
+ @Override
+ public void writeSInt32(int fieldNumber, int value) throws IOException {
+ output.writeSInt32(fieldNumber, value);
+ }
+
+ @Override
+ public void writeSInt64(int fieldNumber, long value) throws IOException {
+ output.writeSInt64(fieldNumber, value);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value) throws IOException {
+ output.writeMessage(fieldNumber, (MessageLite) value);
+ }
+
+ @Override
+ public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
+ output.writeMessage(fieldNumber, (MessageLite) value, schema);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value) throws IOException {
+ output.writeGroup(fieldNumber, (MessageLite) value);
+ }
+
+ @Override
+ public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
+ output.writeGroup(fieldNumber, (MessageLite) value, schema);
+ }
+
+ @Override
+ public void writeStartGroup(int fieldNumber) throws IOException {
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
+ }
+
+ @Override
+ public void writeEndGroup(int fieldNumber) throws IOException {
+ output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException {
+ if (value instanceof ByteString) {
+ output.writeRawMessageSetExtension(fieldNumber, (ByteString) value);
+ } else {
+ output.writeMessageSetExtension(fieldNumber, (MessageLite) value);
+ }
+ }
+
+ @Override
+ public void writeInt32List(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeInt32SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeInt32NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeInt32(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeFixed32SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFixed32NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFixed32(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeInt64SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeInt64NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeInt64(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeUInt64List(int fieldNumber, List<Long> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeUInt64SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeUInt64NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeUInt64(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeFixed64List(int fieldNumber, List<Long> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeFixed64SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFixed64NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFixed64(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeFloatList(int fieldNumber, List<Float> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeFloatSizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFloatNoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeFloat(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeDoubleList(int fieldNumber, List<Double> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeDoubleSizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeDoubleNoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeDouble(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeEnumList(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeEnumSizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeEnumNoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeEnum(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeBoolSizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeBoolNoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeBool(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeStringList(int fieldNumber, List<String> value) throws IOException {
+ if (value instanceof LazyStringList) {
+ final LazyStringList lazyList = (LazyStringList) value;
+ for (int i = 0; i < value.size(); ++i) {
+ writeLazyString(fieldNumber, lazyList.getRaw(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeString(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ private void writeLazyString(int fieldNumber, Object value) throws IOException {
+ if (value instanceof String) {
+ output.writeString(fieldNumber, (String) value);
+ } else {
+ output.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ @Override
+ public void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeBytes(fieldNumber, value.get(i));
+ }
+ }
+
+ @Override
+ public void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeUInt32SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeUInt32NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeUInt32(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeSFixed32SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSFixed32NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSFixed32(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeSFixed64SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSFixed64NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSFixed64(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeSInt32SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSInt32NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSInt32(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeSInt64List(int fieldNumber, List<Long> value, boolean packed)
+ throws IOException {
+ if (packed) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+
+ // Compute and write the length of the data.
+ int dataSize = 0;
+ for (int i = 0; i < value.size(); ++i) {
+ dataSize += CodedOutputStream.computeSInt64SizeNoTag(value.get(i));
+ }
+ output.writeUInt32NoTag(dataSize);
+
+ // Write the data itself, without any tags.
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSInt64NoTag(value.get(i));
+ }
+ } else {
+ for (int i = 0; i < value.size(); ++i) {
+ output.writeSInt64(fieldNumber, value.get(i));
+ }
+ }
+ }
+
+ @Override
+ public void writeMessageList(int fieldNumber, List<?> value) throws IOException {
+ for (int i = 0; i < value.size(); ++i) {
+ writeMessage(fieldNumber, value.get(i));
+ }
+ }
+
+ @Override
+ public void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException {
+ for (int i = 0; i < value.size(); ++i) {
+ writeMessage(fieldNumber, value.get(i), schema);
+ }
+ }
+
+ @Override
+ public void writeGroupList(int fieldNumber, List<?> value) throws IOException {
+ for (int i = 0; i < value.size(); ++i) {
+ writeGroup(fieldNumber, value.get(i));
+ }
+ }
+
+ @Override
+ public void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException {
+ for (int i = 0; i < value.size(); ++i) {
+ writeGroup(fieldNumber, value.get(i), schema);
+ }
+ }
+
+ @Override
+ public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
+ throws IOException {
+ if (output.isSerializationDeterministic()) {
+ writeDeterministicMap(fieldNumber, metadata, map);
+ return;
+ }
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(
+ MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue()));
+ MapEntryLite.writeTo(output, metadata, entry.getKey(), entry.getValue());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <K, V> void writeDeterministicMap(
+ int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map) throws IOException {
+ switch (metadata.keyType) {
+ case BOOL:
+ V value;
+ if ((value = map.get(Boolean.FALSE)) != null) {
+ writeDeterministicBooleanMapEntry(
+ fieldNumber, /* key= */ false, value, (MapEntryLite.Metadata<Boolean, V>) metadata);
+ }
+ if ((value = map.get(Boolean.TRUE)) != null) {
+ writeDeterministicBooleanMapEntry(
+ fieldNumber, /* key= */ true, value, (MapEntryLite.Metadata<Boolean, V>) metadata);
+ }
+ break;
+ case FIXED32:
+ case INT32:
+ case SFIXED32:
+ case SINT32:
+ case UINT32:
+ writeDeterministicIntegerMap(
+ fieldNumber, (MapEntryLite.Metadata<Integer, V>) metadata, (Map<Integer, V>) map);
+ break;
+ case FIXED64:
+ case INT64:
+ case SFIXED64:
+ case SINT64:
+ case UINT64:
+ writeDeterministicLongMap(
+ fieldNumber, (MapEntryLite.Metadata<Long, V>) metadata, (Map<Long, V>) map);
+ break;
+ case STRING:
+ writeDeterministicStringMap(
+ fieldNumber, (MapEntryLite.Metadata<String, V>) metadata, (Map<String, V>) map);
+ break;
+ default:
+ throw new IllegalArgumentException("does not support key type: " + metadata.keyType);
+ }
+ }
+
+ private <V> void writeDeterministicBooleanMapEntry(
+ int fieldNumber, boolean key, V value, MapEntryLite.Metadata<Boolean, V> metadata)
+ throws IOException {
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
+ MapEntryLite.writeTo(output, metadata, key, value);
+ }
+
+ private <V> void writeDeterministicIntegerMap(
+ int fieldNumber, MapEntryLite.Metadata<Integer, V> metadata, Map<Integer, V> map)
+ throws IOException {
+ int[] keys = new int[map.size()];
+ int index = 0;
+ for (int k : map.keySet()) {
+ keys[index++] = k;
+ }
+ Arrays.sort(keys);
+ for (int key : keys) {
+ V value = map.get(key);
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
+ MapEntryLite.writeTo(output, metadata, key, value);
+ }
+ }
+
+ private <V> void writeDeterministicLongMap(
+ int fieldNumber, MapEntryLite.Metadata<Long, V> metadata, Map<Long, V> map)
+ throws IOException {
+ long[] keys = new long[map.size()];
+ int index = 0;
+ for (long k : map.keySet()) {
+ keys[index++] = k;
+ }
+ Arrays.sort(keys);
+ for (long key : keys) {
+ V value = map.get(key);
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
+ MapEntryLite.writeTo(output, metadata, key, value);
+ }
+ }
+
+ private <V> void writeDeterministicStringMap(
+ int fieldNumber, MapEntryLite.Metadata<String, V> metadata, Map<String, V> map)
+ throws IOException {
+ String[] keys = new String[map.size()];
+ int index = 0;
+ for (String k : map.keySet()) {
+ keys[index++] = k;
+ }
+ Arrays.sort(keys);
+ for (String key : keys) {
+ V value = map.get(key);
+ output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
+ output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
+ MapEntryLite.writeTo(output, metadata, key, value);
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java
new file mode 100755
index 000000000..cd29b7beb
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java
@@ -0,0 +1,693 @@
+// 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.FieldInfo.forField;
+import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier;
+import static com.google.protobuf.FieldInfo.forMapField;
+import static com.google.protobuf.FieldInfo.forOneofMemberField;
+import static com.google.protobuf.FieldInfo.forPackedField;
+import static com.google.protobuf.FieldInfo.forPackedFieldWithEnumVerifier;
+import static com.google.protobuf.FieldInfo.forProto2OptionalField;
+import static com.google.protobuf.FieldInfo.forProto2RequiredField;
+import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
+
+import com.google.protobuf.Descriptors.Descriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FieldDescriptor.Type;
+import com.google.protobuf.Descriptors.OneofDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+import java.util.concurrent.ConcurrentHashMap;
+
+/** A factory for message info based on protobuf descriptors for a {@link GeneratedMessageV3}. */
+@ExperimentalApi
+final class DescriptorMessageInfoFactory implements MessageInfoFactory {
+ private static final String GET_DEFAULT_INSTANCE_METHOD_NAME = "getDefaultInstance";
+ private static final DescriptorMessageInfoFactory instance = new DescriptorMessageInfoFactory();
+ private static final Set<String> specialFieldNames =
+ new HashSet<>(Arrays.asList("cached_size", "serialized_size", "class"));
+
+ // Disallow construction - it's a singleton.
+ private DescriptorMessageInfoFactory() {}
+
+ public static DescriptorMessageInfoFactory getInstance() {
+ return instance;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> messageType) {
+ return GeneratedMessageV3.class.isAssignableFrom(messageType);
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> messageType) {
+ if (!GeneratedMessageV3.class.isAssignableFrom(messageType)) {
+ throw new IllegalArgumentException("Unsupported message type: " + messageType.getName());
+ }
+
+ return convert(messageType, descriptorForType(messageType));
+ }
+
+ private static Message getDefaultInstance(Class<?> messageType) {
+ try {
+ Method method = messageType.getDeclaredMethod(GET_DEFAULT_INSTANCE_METHOD_NAME);
+ return (Message) method.invoke(null);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ "Unable to get default instance for message class " + messageType.getName(), e);
+ }
+ }
+
+ private static Descriptor descriptorForType(Class<?> messageType) {
+ return getDefaultInstance(messageType).getDescriptorForType();
+ }
+
+ private static MessageInfo convert(Class<?> messageType, Descriptor messageDescriptor) {
+ switch (messageDescriptor.getFile().getSyntax()) {
+ case PROTO2:
+ return convertProto2(messageType, messageDescriptor);
+ case PROTO3:
+ return convertProto3(messageType, messageDescriptor);
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported syntax: " + messageDescriptor.getFile().getSyntax());
+ }
+ }
+
+ /**
+ * A helper class to determine whether a message type needs to implement {@code isInitialized()}.
+ *
+ * <p>If a message type doesn't have any required fields or extensions (directly and
+ * transitively), it doesn't need to implement isInitialized() and can always return true there.
+ * It's a bit tricky to determine whether a type has transitive required fields because protobuf
+ * allows cycle references within the same .proto file (e.g., message Foo has a Bar field, and
+ * message Bar has a Foo field). For that we use Tarjan's strongly connected components algorithm
+ * to classify messages into strongly connected groups. Messages in the same group are
+ * transitively including each other, so they should either all have transitive required fields
+ * (or extensions), or none have.
+ *
+ * <p>The code is adapted from the C++ implementation:
+ * https://cs.corp.google.com/piper///depot/google3/net/proto2/compiler/cpp/internal/helpers.h?type=cs&rcl=161303268&l=346
+ *
+ * <p>This class is thread-safe.
+ */
+ static class IsInitializedCheckAnalyzer {
+
+ private final Map<Descriptor, Boolean> resultCache =
+ new ConcurrentHashMap<Descriptor, Boolean>();
+
+ // The following data members are part of Tarjan's SCC algorithm. See:
+ // https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
+ private int index = 0;
+ private final Stack<Node> stack = new Stack<Node>();
+ private final Map<Descriptor, Node> nodeCache = new HashMap<Descriptor, Node>();
+
+ public boolean needsIsInitializedCheck(Descriptor descriptor) {
+ Boolean cachedValue = resultCache.get(descriptor);
+ if (cachedValue != null) {
+ return cachedValue;
+ }
+ synchronized (this) {
+ // Double-check the cache because some other thread may have updated it while we
+ // were acquiring the lock.
+ cachedValue = resultCache.get(descriptor);
+ if (cachedValue != null) {
+ return cachedValue;
+ }
+ return dfs(descriptor).component.needsIsInitializedCheck;
+ }
+ }
+
+ private static class Node {
+ final Descriptor descriptor;
+ final int index;
+ int lowLink;
+ StronglyConnectedComponent component; // null if the node is still on stack.
+
+ Node(Descriptor descriptor, int index) {
+ this.descriptor = descriptor;
+ this.index = index;
+ this.lowLink = index;
+ this.component = null;
+ }
+ }
+
+ private static class StronglyConnectedComponent {
+ final List<Descriptor> messages = new ArrayList<Descriptor>();
+ boolean needsIsInitializedCheck = false;
+ }
+
+ private Node dfs(Descriptor descriptor) {
+ Node result = new Node(descriptor, index++);
+ stack.push(result);
+ nodeCache.put(descriptor, result);
+
+ // Recurse the fields / nodes in graph
+ for (FieldDescriptor field : descriptor.getFields()) {
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ Node child = nodeCache.get(field.getMessageType());
+ if (child == null) {
+ // Unexplored node
+ child = dfs(field.getMessageType());
+ result.lowLink = Math.min(result.lowLink, child.lowLink);
+ } else {
+ if (child.component == null) {
+ // Still in the stack so we found a back edge.
+ result.lowLink = Math.min(result.lowLink, child.lowLink);
+ }
+ }
+ }
+ }
+
+ if (result.index == result.lowLink) {
+ // This is the root of a strongly connected component.
+ StronglyConnectedComponent component = new StronglyConnectedComponent();
+ while (true) {
+ Node node = stack.pop();
+ node.component = component;
+ component.messages.add(node.descriptor);
+ if (node == result) {
+ break;
+ }
+ }
+
+ analyze(component);
+ }
+
+ return result;
+ }
+
+ // Determine whether messages in this SCC needs isInitialized check.
+ private void analyze(StronglyConnectedComponent component) {
+ boolean needsIsInitializedCheck = false;
+ loop:
+ for (Descriptor descriptor : component.messages) {
+ if (descriptor.isExtendable()) {
+ needsIsInitializedCheck = true;
+ break;
+ }
+
+ for (FieldDescriptor field : descriptor.getFields()) {
+ if (field.isRequired()) {
+ needsIsInitializedCheck = true;
+ break loop;
+ }
+
+ if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ // Since we are analyzing the graph bottom-up, all referenced fields should either be
+ // in this same component or in a different already-analyzed component.
+ Node node = nodeCache.get(field.getMessageType());
+ if (node.component != component) {
+ if (node.component.needsIsInitializedCheck) {
+ needsIsInitializedCheck = true;
+ break loop;
+ }
+ }
+ }
+ }
+ }
+
+ component.needsIsInitializedCheck = needsIsInitializedCheck;
+
+ for (Descriptor descriptor : component.messages) {
+ resultCache.put(descriptor, component.needsIsInitializedCheck);
+ }
+ }
+ }
+
+ private static IsInitializedCheckAnalyzer isInitializedCheckAnalyzer =
+ new IsInitializedCheckAnalyzer();
+
+ private static boolean needsIsInitializedCheck(Descriptor descriptor) {
+ return isInitializedCheckAnalyzer.needsIsInitializedCheck(descriptor);
+ }
+
+ private static StructuralMessageInfo convertProto2(
+ Class<?> messageType, Descriptor messageDescriptor) {
+ List<FieldDescriptor> fieldDescriptors = messageDescriptor.getFields();
+ StructuralMessageInfo.Builder builder =
+ StructuralMessageInfo.newBuilder(fieldDescriptors.size());
+ builder.withDefaultInstance(getDefaultInstance(messageType));
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withMessageSetWireFormat(messageDescriptor.getOptions().getMessageSetWireFormat());
+
+ OneofState oneofState = new OneofState();
+ int bitFieldIndex = 0;
+ int presenceMask = 1;
+ Field bitField = null;
+
+ // Fields in the descriptor are ordered by the index position in which they appear in the
+ // proto file. This is the same order used to determine the presence mask used in the
+ // bitFields. So to determine the appropriate presence mask to be used for a field, we simply
+ // need to shift the presence mask whenever a presence-checked field is encountered.
+ for (int i = 0; i < fieldDescriptors.size(); ++i) {
+ final FieldDescriptor fd = fieldDescriptors.get(i);
+ boolean enforceUtf8 = fd.getFile().getOptions().getJavaStringCheckUtf8();
+ Internal.EnumVerifier enumVerifier = null;
+ if (fd.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
+ enumVerifier =
+ new Internal.EnumVerifier() {
+ @Override
+ public boolean isInRange(int number) {
+ return fd.getEnumType().findValueByNumber(number) != null;
+ }
+ };
+ }
+ if (fd.getContainingOneof() != null) {
+ // Build a oneof member field.
+ builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, enumVerifier));
+ } else {
+ Field field = field(messageType, fd);
+ int number = fd.getNumber();
+ FieldType type = getFieldType(fd);
+
+ if (fd.isMapField()) {
+ // Map field points to an auto-generated message entry type with the definition:
+ // message MapEntry {
+ // K key = 1;
+ // V value = 2;
+ // }
+ final FieldDescriptor valueField = fd.getMessageType().findFieldByNumber(2);
+ if (valueField.getJavaType() == Descriptors.FieldDescriptor.JavaType.ENUM) {
+ enumVerifier =
+ new Internal.EnumVerifier() {
+ @Override
+ public boolean isInRange(int number) {
+ return valueField.getEnumType().findValueByNumber(number) != null;
+ }
+ };
+ }
+ builder.withField(
+ forMapField(
+ field,
+ number,
+ SchemaUtil.getMapDefaultEntry(messageType, fd.getName()),
+ enumVerifier));
+ continue;
+ }
+
+ if (fd.isRepeated()) {
+ // Repeated fields are not presence-checked.
+ if (enumVerifier != null) {
+ if (fd.isPacked()) {
+ builder.withField(
+ forPackedFieldWithEnumVerifier(
+ field, number, type, enumVerifier, cachedSizeField(messageType, fd)));
+ } else {
+ builder.withField(forFieldWithEnumVerifier(field, number, type, enumVerifier));
+ }
+ } else if (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ builder.withField(
+ forRepeatedMessageField(
+ field, number, type, getTypeForRepeatedMessageField(messageType, fd)));
+ } else {
+ if (fd.isPacked()) {
+ builder.withField(
+ forPackedField(field, number, type, cachedSizeField(messageType, fd)));
+ } else {
+ builder.withField(forField(field, number, type, enforceUtf8));
+ }
+ }
+ continue;
+ }
+
+ if (bitField == null) {
+ // Lazy-create the next bitfield since we know it must exist.
+ bitField = bitField(messageType, bitFieldIndex);
+ }
+
+ // It's a presence-checked field.
+ if (fd.isRequired()) {
+ builder.withField(
+ forProto2RequiredField(
+ field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier));
+ } else {
+ builder.withField(
+ forProto2OptionalField(
+ field, number, type, bitField, presenceMask, enforceUtf8, enumVerifier));
+ }
+ }
+
+ // Update the presence mask for the next iteration. If the shift clears out the mask, we will
+ // go to the next bitField.
+ presenceMask <<= 1;
+ if (presenceMask == 0) {
+ bitField = null;
+ presenceMask = 1;
+ bitFieldIndex++;
+ }
+ }
+
+ List<Integer> fieldsToCheckIsInitialized = new ArrayList<Integer>();
+ for (int i = 0; i < fieldDescriptors.size(); ++i) {
+ FieldDescriptor fd = fieldDescriptors.get(i);
+ if (fd.isRequired()
+ || (fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+ && needsIsInitializedCheck(fd.getMessageType()))) {
+ fieldsToCheckIsInitialized.add(fd.getNumber());
+ }
+ }
+ int[] numbers = new int[fieldsToCheckIsInitialized.size()];
+ for (int i = 0; i < fieldsToCheckIsInitialized.size(); i++) {
+ numbers[i] = fieldsToCheckIsInitialized.get(i);
+ }
+ builder.withCheckInitialized(numbers);
+
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo convertProto3(
+ Class<?> messageType, Descriptor messageDescriptor) {
+ List<FieldDescriptor> fieldDescriptors = messageDescriptor.getFields();
+ StructuralMessageInfo.Builder builder =
+ StructuralMessageInfo.newBuilder(fieldDescriptors.size());
+ builder.withDefaultInstance(getDefaultInstance(messageType));
+ builder.withSyntax(ProtoSyntax.PROTO3);
+
+ OneofState oneofState = new OneofState();
+ boolean enforceUtf8 = true;
+ for (int i = 0; i < fieldDescriptors.size(); ++i) {
+ FieldDescriptor fd = fieldDescriptors.get(i);
+ if (fd.getContainingOneof() != null) {
+ // Build a oneof member field.
+ builder.withField(buildOneofMember(messageType, fd, oneofState, enforceUtf8, null));
+ continue;
+ }
+ if (fd.isMapField()) {
+ builder.withField(
+ forMapField(
+ field(messageType, fd),
+ fd.getNumber(),
+ SchemaUtil.getMapDefaultEntry(messageType, fd.getName()),
+ null));
+ continue;
+ }
+ if (fd.isRepeated() && fd.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+ builder.withField(
+ forRepeatedMessageField(
+ field(messageType, fd),
+ fd.getNumber(),
+ getFieldType(fd),
+ getTypeForRepeatedMessageField(messageType, fd)));
+ continue;
+ }
+ if (fd.isPacked()) {
+ builder.withField(
+ forPackedField(
+ field(messageType, fd),
+ fd.getNumber(),
+ getFieldType(fd),
+ cachedSizeField(messageType, fd)));
+ } else {
+ builder.withField(
+ forField(field(messageType, fd), fd.getNumber(), getFieldType(fd), enforceUtf8));
+ }
+ }
+
+ return builder.build();
+ }
+
+ /** Builds info for a oneof member field. */
+ private static FieldInfo buildOneofMember(
+ Class<?> messageType,
+ FieldDescriptor fd,
+ OneofState oneofState,
+ boolean enforceUtf8,
+ Internal.EnumVerifier enumVerifier) {
+ OneofInfo oneof = oneofState.getOneof(messageType, fd.getContainingOneof());
+ FieldType type = getFieldType(fd);
+ Class<?> oneofStoredType = getOneofStoredType(messageType, fd, type);
+ return forOneofMemberField(
+ fd.getNumber(), type, oneof, oneofStoredType, enforceUtf8, enumVerifier);
+ }
+
+ private static Class<?> getOneofStoredType(
+ Class<?> messageType, FieldDescriptor fd, FieldType type) {
+ switch (type.getJavaType()) {
+ case BOOLEAN:
+ return Boolean.class;
+ case BYTE_STRING:
+ return ByteString.class;
+ case DOUBLE:
+ return Double.class;
+ case FLOAT:
+ return Float.class;
+ case ENUM:
+ case INT:
+ return Integer.class;
+ case LONG:
+ return Long.class;
+ case STRING:
+ return String.class;
+ case MESSAGE:
+ return getOneofStoredTypeForMessage(messageType, fd);
+ default:
+ throw new IllegalArgumentException("Invalid type for oneof: " + type);
+ }
+ }
+
+ private static FieldType getFieldType(FieldDescriptor fd) {
+ switch (fd.getType()) {
+ case BOOL:
+ if (!fd.isRepeated()) {
+ return FieldType.BOOL;
+ }
+ return fd.isPacked() ? FieldType.BOOL_LIST_PACKED : FieldType.BOOL_LIST;
+ case BYTES:
+ return fd.isRepeated() ? FieldType.BYTES_LIST : FieldType.BYTES;
+ case DOUBLE:
+ if (!fd.isRepeated()) {
+ return FieldType.DOUBLE;
+ }
+ return fd.isPacked() ? FieldType.DOUBLE_LIST_PACKED : FieldType.DOUBLE_LIST;
+ case ENUM:
+ if (!fd.isRepeated()) {
+ return FieldType.ENUM;
+ }
+ return fd.isPacked() ? FieldType.ENUM_LIST_PACKED : FieldType.ENUM_LIST;
+ case FIXED32:
+ if (!fd.isRepeated()) {
+ return FieldType.FIXED32;
+ }
+ return fd.isPacked() ? FieldType.FIXED32_LIST_PACKED : FieldType.FIXED32_LIST;
+ case FIXED64:
+ if (!fd.isRepeated()) {
+ return FieldType.FIXED64;
+ }
+ return fd.isPacked() ? FieldType.FIXED64_LIST_PACKED : FieldType.FIXED64_LIST;
+ case FLOAT:
+ if (!fd.isRepeated()) {
+ return FieldType.FLOAT;
+ }
+ return fd.isPacked() ? FieldType.FLOAT_LIST_PACKED : FieldType.FLOAT_LIST;
+ case GROUP:
+ return fd.isRepeated() ? FieldType.GROUP_LIST : FieldType.GROUP;
+ case INT32:
+ if (!fd.isRepeated()) {
+ return FieldType.INT32;
+ }
+ return fd.isPacked() ? FieldType.INT32_LIST_PACKED : FieldType.INT32_LIST;
+ case INT64:
+ if (!fd.isRepeated()) {
+ return FieldType.INT64;
+ }
+ return fd.isPacked() ? FieldType.INT64_LIST_PACKED : FieldType.INT64_LIST;
+ case MESSAGE:
+ if (fd.isMapField()) {
+ return FieldType.MAP;
+ }
+ return fd.isRepeated() ? FieldType.MESSAGE_LIST : FieldType.MESSAGE;
+ case SFIXED32:
+ if (!fd.isRepeated()) {
+ return FieldType.SFIXED32;
+ }
+ return fd.isPacked() ? FieldType.SFIXED32_LIST_PACKED : FieldType.SFIXED32_LIST;
+ case SFIXED64:
+ if (!fd.isRepeated()) {
+ return FieldType.SFIXED64;
+ }
+ return fd.isPacked() ? FieldType.SFIXED64_LIST_PACKED : FieldType.SFIXED64_LIST;
+ case SINT32:
+ if (!fd.isRepeated()) {
+ return FieldType.SINT32;
+ }
+ return fd.isPacked() ? FieldType.SINT32_LIST_PACKED : FieldType.SINT32_LIST;
+ case SINT64:
+ if (!fd.isRepeated()) {
+ return FieldType.SINT64;
+ }
+ return fd.isPacked() ? FieldType.SINT64_LIST_PACKED : FieldType.SINT64_LIST;
+ case STRING:
+ return fd.isRepeated() ? FieldType.STRING_LIST : FieldType.STRING;
+ case UINT32:
+ if (!fd.isRepeated()) {
+ return FieldType.UINT32;
+ }
+ return fd.isPacked() ? FieldType.UINT32_LIST_PACKED : FieldType.UINT32_LIST;
+ case UINT64:
+ if (!fd.isRepeated()) {
+ return FieldType.UINT64;
+ }
+ return fd.isPacked() ? FieldType.UINT64_LIST_PACKED : FieldType.UINT64_LIST;
+ default:
+ throw new IllegalArgumentException("Unsupported field type: " + fd.getType());
+ }
+ }
+
+ private static Field bitField(Class<?> messageType, int index) {
+ return field(messageType, "bitField" + index + "_");
+ }
+
+ private static Field field(Class<?> messageType, FieldDescriptor fd) {
+ return field(messageType, getFieldName(fd));
+ }
+
+ private static Field cachedSizeField(Class<?> messageType, FieldDescriptor fd) {
+ return field(messageType, getCachedSizeFieldName(fd));
+ }
+
+ private static Field field(Class<?> messageType, String fieldName) {
+ try {
+ return messageType.getDeclaredField(fieldName);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(
+ "Unable to find field " + fieldName + " in message class " + messageType.getName());
+ }
+ }
+
+ static String getFieldName(FieldDescriptor fd) {
+ String name = (fd.getType() == FieldDescriptor.Type.GROUP)
+ ? fd.getMessageType().getName()
+ : fd.getName();
+ String suffix = specialFieldNames.contains(name) ? "__" : "_";
+ return snakeCaseToCamelCase(name) + suffix;
+ }
+
+ private static String getCachedSizeFieldName(FieldDescriptor fd) {
+ return snakeCaseToCamelCase(fd.getName()) + "MemoizedSerializedSize";
+ }
+
+ /**
+ * This method must match exactly with the corresponding function in protocol compiler. See:
+ * https://github.com/google/protobuf/blob/v3.0.0/src/google/protobuf/compiler/java/java_helpers.cc#L153
+ */
+ private static String snakeCaseToCamelCase(String snakeCase) {
+ StringBuilder sb = new StringBuilder(snakeCase.length() + 1);
+ boolean capNext = false;
+ for (int ctr = 0; ctr < snakeCase.length(); ctr++) {
+ char next = snakeCase.charAt(ctr);
+ if (next == '_') {
+ capNext = true;
+ } else if (Character.isDigit(next)) {
+ sb.append(next);
+ capNext = true;
+ } else if (capNext) {
+ sb.append(Character.toUpperCase(next));
+ capNext = false;
+ } else if (ctr == 0) {
+ sb.append(Character.toLowerCase(next));
+ } else {
+ sb.append(next);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Inspects the message to identify the stored type for a message field that is part of a oneof.
+ */
+ private static Class<?> getOneofStoredTypeForMessage(Class<?> messageType, FieldDescriptor fd) {
+ try {
+ String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName();
+ Method getter = messageType.getDeclaredMethod(getterForField(name));
+ return getter.getReturnType();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Inspects the message to identify the message type of a repeated message field. */
+ private static Class<?> getTypeForRepeatedMessageField(Class<?> messageType, FieldDescriptor fd) {
+ try {
+ String name = fd.getType() == Type.GROUP ? fd.getMessageType().getName() : fd.getName();
+ Method getter = messageType.getDeclaredMethod(getterForField(name), int.class);
+ return getter.getReturnType();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Constructs the name of the get method for the given field in the proto. */
+ private static String getterForField(String snakeCase) {
+ String camelCase = snakeCaseToCamelCase(snakeCase);
+ StringBuilder builder = new StringBuilder("get");
+ // Capitalize the first character in the field name.
+ builder.append(Character.toUpperCase(camelCase.charAt(0)));
+ builder.append(camelCase.substring(1, camelCase.length()));
+ return builder.toString();
+ }
+
+ private static final class OneofState {
+ private OneofInfo[] oneofs = new OneofInfo[2];
+
+ OneofInfo getOneof(Class<?> messageType, OneofDescriptor desc) {
+ int index = desc.getIndex();
+ if (index >= oneofs.length) {
+ // Grow the array.
+ oneofs = Arrays.copyOf(oneofs, index * 2);
+ }
+ OneofInfo info = oneofs[index];
+ if (info == null) {
+ info = newInfo(messageType, desc);
+ oneofs[index] = info;
+ }
+ return info;
+ }
+
+ private static OneofInfo newInfo(Class<?> messageType, OneofDescriptor desc) {
+ String camelCase = snakeCaseToCamelCase(desc.getName());
+ String valueFieldName = camelCase + "_";
+ String caseFieldName = camelCase + "Case_";
+
+ return new OneofInfo(
+ desc.getIndex(), field(messageType, caseFieldName), field(messageType, valueFieldName));
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
index 0ce5f5493..11843b6c3 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -110,12 +110,23 @@ public class ExtensionRegistryLite {
return ExtensionRegistryFactory.create();
}
+ private static volatile ExtensionRegistryLite emptyRegistry;
+
/**
* 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();
+ ExtensionRegistryLite result = emptyRegistry;
+ if (result == null) {
+ synchronized (ExtensionRegistryLite.class) {
+ result = emptyRegistry;
+ if (result == null) {
+ result = emptyRegistry = ExtensionRegistryFactory.createEmpty();
+ }
+ }
+ }
+ return result;
}
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java
new file mode 100755
index 000000000..2eae22d26
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchema.java
@@ -0,0 +1,98 @@
+// 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.Map;
+
+abstract class ExtensionSchema<T extends FieldSet.FieldDescriptorLite<T>> {
+
+ /** Returns true for messages that support extensions. */
+ abstract boolean hasExtensions(MessageLite prototype);
+
+ /** Returns the extension {@link FieldSet} for the message instance. */
+ abstract FieldSet<T> getExtensions(Object message);
+
+ /** Replaces the extension {@link FieldSet} for the message instance. */
+ abstract void setExtensions(Object message, FieldSet<T> extensions);
+
+ /** Returns the extension {@link FieldSet} and ensures it's mutable. */
+ abstract FieldSet<T> getMutableExtensions(Object message);
+
+ /** Marks the extension {@link FieldSet} as immutable. */
+ abstract void makeImmutable(Object message);
+
+ /**
+ * Parses an extension. Returns the passed-in unknownFields parameter if no unknown enum value is
+ * found or a modified unknownFields (a new instance if the passed-in unknownFields is null)
+ * containing unknown enum values found while parsing.
+ *
+ * @param <UT> The type used to store unknown fields. It's either UnknownFieldSet in full runtime
+ * or UnknownFieldSetLite in lite runtime.
+ */
+ abstract <UT, UB> UB parseExtension(
+ Reader reader,
+ Object extension,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<T> extensions,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema)
+ throws IOException;
+
+ /** Gets the field number of an extension entry. */
+ abstract int extensionNumber(Map.Entry<?, ?> extension);
+
+ /** Serializes one extension entry. */
+ abstract void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException;
+
+ /** Finds an extension by field number. */
+ abstract Object findExtensionByNumber(
+ ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number);
+
+ /** Parses a length-prefixed MessageSet item from the reader. */
+ abstract void parseLengthPrefixedMessageSetItem(
+ Reader reader,
+ Object extension,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<T> extensions)
+ throws IOException;
+
+ /**
+ * Parses the entire content of a {@link ByteString} as one MessageSet item. Unlike {@link
+ * #parseLengthPrefixedMessageSetItem}, there isn't a length-prefix.
+ */
+ abstract void parseMessageSetItem(
+ ByteString data,
+ Object extension,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<T> extensions)
+ throws IOException;
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java
new file mode 100755
index 000000000..90558518b
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java
@@ -0,0 +1,547 @@
+// 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 java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("unchecked")
+final class ExtensionSchemaFull extends ExtensionSchema<FieldDescriptor> {
+
+ private static final long EXTENSION_FIELD_OFFSET = getExtensionsFieldOffset();
+
+ private static <T> long getExtensionsFieldOffset() {
+ try {
+ Field field = GeneratedMessageV3.ExtendableMessage.class.getDeclaredField("extensions");
+ return UnsafeUtil.objectFieldOffset(field);
+ } catch (Throwable e) {
+ throw new IllegalStateException("Unable to lookup extension field offset");
+ }
+ }
+
+ @Override
+ boolean hasExtensions(MessageLite prototype) {
+ return prototype instanceof GeneratedMessageV3.ExtendableMessage;
+ }
+
+ @Override
+ public FieldSet<FieldDescriptor> getExtensions(Object message) {
+ return (FieldSet<FieldDescriptor>) UnsafeUtil.getObject(message, EXTENSION_FIELD_OFFSET);
+ }
+
+ @Override
+ void setExtensions(Object message, FieldSet<FieldDescriptor> extensions) {
+ UnsafeUtil.putObject(message, EXTENSION_FIELD_OFFSET, extensions);
+ }
+
+ @Override
+ FieldSet<FieldDescriptor> getMutableExtensions(Object message) {
+ FieldSet<FieldDescriptor> extensions = getExtensions(message);
+ if (extensions.isImmutable()) {
+ extensions = extensions.clone();
+ setExtensions(message, extensions);
+ }
+ return extensions;
+ }
+
+ @Override
+ void makeImmutable(Object message) {
+ getExtensions(message).makeImmutable();
+ }
+
+ @Override
+ <UT, UB> UB parseExtension(
+ Reader reader,
+ Object extensionObject,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<FieldDescriptor> extensions,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema)
+ throws IOException {
+ ExtensionRegistry.ExtensionInfo extension = (ExtensionRegistry.ExtensionInfo) extensionObject;
+ int fieldNumber = extension.descriptor.getNumber();
+
+ if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
+ Object value = null;
+ switch (extension.descriptor.getLiteType()) {
+ case DOUBLE:
+ {
+ List<Double> list = new ArrayList<Double>();
+ reader.readDoubleList(list);
+ value = list;
+ break;
+ }
+ case FLOAT:
+ {
+ List<Float> list = new ArrayList<Float>();
+ reader.readFloatList(list);
+ value = list;
+ break;
+ }
+ case INT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readInt64List(list);
+ value = list;
+ break;
+ }
+ case UINT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readUInt64List(list);
+ value = list;
+ break;
+ }
+ case INT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readInt32List(list);
+ value = list;
+ break;
+ }
+ case FIXED64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readFixed64List(list);
+ value = list;
+ break;
+ }
+ case FIXED32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readFixed32List(list);
+ value = list;
+ break;
+ }
+ case BOOL:
+ {
+ List<Boolean> list = new ArrayList<Boolean>();
+ reader.readBoolList(list);
+ value = list;
+ break;
+ }
+ case UINT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readUInt32List(list);
+ value = list;
+ break;
+ }
+ case SFIXED32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readSFixed32List(list);
+ value = list;
+ break;
+ }
+ case SFIXED64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readSFixed64List(list);
+ value = list;
+ break;
+ }
+ case SINT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readSInt32List(list);
+ value = list;
+ break;
+ }
+ case SINT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readSInt64List(list);
+ value = list;
+ break;
+ }
+ case ENUM:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readEnumList(list);
+ List<EnumValueDescriptor> enumList = new ArrayList<EnumValueDescriptor>();
+ for (int number : list) {
+ EnumValueDescriptor enumDescriptor =
+ extension.descriptor.getEnumType().findValueByNumber(number);
+ if (enumDescriptor != null) {
+ enumList.add(enumDescriptor);
+ } else {
+ unknownFields =
+ SchemaUtil.storeUnknownEnum(
+ fieldNumber, number, unknownFields, unknownFieldSchema);
+ }
+ }
+ value = enumList;
+ break;
+ }
+ default:
+ throw new IllegalStateException(
+ "Type cannot be packed: " + extension.descriptor.getLiteType());
+ }
+ extensions.setField(extension.descriptor, value);
+ } else {
+ Object value = null;
+ // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite.
+ if (extension.descriptor.getLiteType() == WireFormat.FieldType.ENUM) {
+ int number = reader.readInt32();
+ Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number);
+ if (enumValue == null) {
+ return SchemaUtil.storeUnknownEnum(
+ fieldNumber, number, unknownFields, unknownFieldSchema);
+ }
+ value = enumValue;
+ } else {
+ switch (extension.descriptor.getLiteType()) {
+ case DOUBLE:
+ value = reader.readDouble();
+ break;
+ case FLOAT:
+ value = reader.readFloat();
+ break;
+ case INT64:
+ value = reader.readInt64();
+ break;
+ case UINT64:
+ value = reader.readUInt64();
+ break;
+ case INT32:
+ value = reader.readInt32();
+ break;
+ case FIXED64:
+ value = reader.readFixed64();
+ break;
+ case FIXED32:
+ value = reader.readFixed32();
+ break;
+ case BOOL:
+ value = reader.readBool();
+ break;
+ case BYTES:
+ value = reader.readBytes();
+ break;
+ case UINT32:
+ value = reader.readUInt32();
+ break;
+ case SFIXED32:
+ value = reader.readSFixed32();
+ break;
+ case SFIXED64:
+ value = reader.readSFixed64();
+ break;
+ case SINT32:
+ value = reader.readSInt32();
+ break;
+ case SINT64:
+ value = reader.readSInt64();
+ break;
+
+ case STRING:
+ value = reader.readString();
+ break;
+ case GROUP:
+ value = reader.readGroup(extension.defaultInstance.getClass(), extensionRegistry);
+ break;
+
+ case MESSAGE:
+ value = reader.readMessage(extension.defaultInstance.getClass(), extensionRegistry);
+ break;
+
+ case ENUM:
+ throw new IllegalStateException("Shouldn't reach here.");
+ }
+ }
+ if (extension.descriptor.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor, value);
+ } else {
+ switch (extension.descriptor.getLiteType()) {
+ case MESSAGE:
+ case GROUP:
+ Object oldValue = extensions.getField(extension.descriptor);
+ if (oldValue != null) {
+ value = Internal.mergeMessage(oldValue, value);
+ }
+ break;
+ default:
+ break;
+ }
+ extensions.setField(extension.descriptor, value);
+ }
+ }
+ return unknownFields;
+ }
+
+ @Override
+ int extensionNumber(Map.Entry<?, ?> extension) {
+ FieldDescriptor descriptor = (FieldDescriptor) extension.getKey();
+ return descriptor.getNumber();
+ }
+
+ @Override
+ void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException {
+ FieldDescriptor descriptor = (FieldDescriptor) extension.getKey();
+ if (descriptor.isRepeated()) {
+ switch (descriptor.getLiteType()) {
+ case DOUBLE:
+ SchemaUtil.writeDoubleList(
+ descriptor.getNumber(),
+ (List<Double>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FLOAT:
+ SchemaUtil.writeFloatList(
+ descriptor.getNumber(),
+ (List<Float>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case INT64:
+ SchemaUtil.writeInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case UINT64:
+ SchemaUtil.writeUInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case INT32:
+ SchemaUtil.writeInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FIXED64:
+ SchemaUtil.writeFixed64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FIXED32:
+ SchemaUtil.writeFixed32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case BOOL:
+ SchemaUtil.writeBoolList(
+ descriptor.getNumber(),
+ (List<Boolean>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case BYTES:
+ SchemaUtil.writeBytesList(
+ descriptor.getNumber(), (List<ByteString>) extension.getValue(), writer);
+ break;
+ case UINT32:
+ SchemaUtil.writeUInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SFIXED32:
+ SchemaUtil.writeSFixed32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SFIXED64:
+ SchemaUtil.writeSFixed64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SINT32:
+ SchemaUtil.writeSInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SINT64:
+ SchemaUtil.writeSInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case ENUM:
+ {
+ List<EnumValueDescriptor> enumList = (List<EnumValueDescriptor>) extension.getValue();
+ List<Integer> list = new ArrayList<Integer>();
+ for (EnumValueDescriptor d : enumList) {
+ list.add(d.getNumber());
+ }
+ SchemaUtil.writeInt32List(descriptor.getNumber(), list, writer, descriptor.isPacked());
+ break;
+ }
+ case STRING:
+ SchemaUtil.writeStringList(
+ descriptor.getNumber(), (List<String>) extension.getValue(), writer);
+ break;
+ case GROUP:
+ SchemaUtil.writeGroupList(descriptor.getNumber(), (List<?>) extension.getValue(), writer);
+ break;
+ case MESSAGE:
+ SchemaUtil.writeMessageList(
+ descriptor.getNumber(), (List<?>) extension.getValue(), writer);
+ break;
+ }
+ } else {
+ switch (descriptor.getLiteType()) {
+ case DOUBLE:
+ writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue());
+ break;
+ case FLOAT:
+ writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue());
+ break;
+ case INT64:
+ writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case UINT64:
+ writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case INT32:
+ writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case FIXED64:
+ writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case FIXED32:
+ writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case BOOL:
+ writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue());
+ break;
+ case BYTES:
+ writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue());
+ break;
+ case UINT32:
+ writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SFIXED32:
+ writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SFIXED64:
+ writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case SINT32:
+ writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SINT64:
+ writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case ENUM:
+ writer.writeInt32(
+ descriptor.getNumber(), ((EnumValueDescriptor) extension.getValue()).getNumber());
+ break;
+ case STRING:
+ writer.writeString(descriptor.getNumber(), (String) extension.getValue());
+ break;
+ case GROUP:
+ writer.writeGroup(descriptor.getNumber(), extension.getValue());
+ break;
+ case MESSAGE:
+ writer.writeMessage(descriptor.getNumber(), extension.getValue());
+ break;
+ }
+ }
+ }
+
+ @Override
+ Object findExtensionByNumber(
+ ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) {
+ return ((ExtensionRegistry) extensionRegistry)
+ .findExtensionByNumber(((Message) defaultInstance).getDescriptorForType(), number);
+ }
+
+ @Override
+ void parseLengthPrefixedMessageSetItem(
+ Reader reader,
+ Object extension,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<FieldDescriptor> extensions)
+ throws IOException {
+ ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension;
+
+ if (ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ Object value =
+ reader.readMessage(extensionInfo.defaultInstance.getClass(), extensionRegistry);
+ extensions.setField(extensionInfo.descriptor, value);
+ } else {
+ extensions.setField(
+ extensionInfo.descriptor,
+ new LazyField(extensionInfo.defaultInstance, extensionRegistry, reader.readBytes()));
+ }
+ }
+
+ @Override
+ void parseMessageSetItem(
+ ByteString data,
+ Object extension,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<FieldDescriptor> extensions)
+ throws IOException {
+ ExtensionRegistry.ExtensionInfo extensionInfo = (ExtensionRegistry.ExtensionInfo) extension;
+ Object value = extensionInfo.defaultInstance.newBuilderForType().buildPartial();
+
+ if (ExtensionRegistryLite.isEagerlyParseMessageSets()) {
+ Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(data.toByteArray()), true);
+ Protobuf.getInstance().mergeFrom(value, reader, extensionRegistry);
+ extensions.setField(extensionInfo.descriptor, value);
+
+ if (reader.getFieldNumber() != Reader.READ_DONE) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ } else {
+ extensions.setField(
+ extensionInfo.descriptor,
+ new LazyField(extensionInfo.defaultInstance, extensionRegistry, data));
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java
new file mode 100755
index 000000000..7f6846eb0
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java
@@ -0,0 +1,541 @@
+// 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.GeneratedMessageLite.ExtensionDescriptor;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("unchecked")
+final class ExtensionSchemaLite extends ExtensionSchema<ExtensionDescriptor> {
+
+ @Override
+ boolean hasExtensions(MessageLite prototype) {
+ return prototype instanceof GeneratedMessageLite.ExtendableMessage;
+ }
+
+ @Override
+ FieldSet<ExtensionDescriptor> getExtensions(Object message) {
+ return ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).extensions;
+ }
+
+ @Override
+ void setExtensions(Object message, FieldSet<ExtensionDescriptor> extensions) {
+ ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).extensions = extensions;
+ }
+
+ @Override
+ FieldSet<ExtensionDescriptor> getMutableExtensions(Object message) {
+ return ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable();
+ }
+
+ @Override
+ void makeImmutable(Object message) {
+ getExtensions(message).makeImmutable();
+ }
+
+ @Override
+ <UT, UB> UB parseExtension(
+ Reader reader,
+ Object extensionObject,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<ExtensionDescriptor> extensions,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema)
+ throws IOException {
+ GeneratedMessageLite.GeneratedExtension<?, ?> extension =
+ (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject;
+ int fieldNumber = extension.getNumber();
+
+ if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) {
+ Object value = null;
+ switch (extension.getLiteType()) {
+ case DOUBLE:
+ {
+ List<Double> list = new ArrayList<Double>();
+ reader.readDoubleList(list);
+ value = list;
+ break;
+ }
+ case FLOAT:
+ {
+ List<Float> list = new ArrayList<Float>();
+ reader.readFloatList(list);
+ value = list;
+ break;
+ }
+ case INT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readInt64List(list);
+ value = list;
+ break;
+ }
+ case UINT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readUInt64List(list);
+ value = list;
+ break;
+ }
+ case INT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readInt32List(list);
+ value = list;
+ break;
+ }
+ case FIXED64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readFixed64List(list);
+ value = list;
+ break;
+ }
+ case FIXED32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readFixed32List(list);
+ value = list;
+ break;
+ }
+ case BOOL:
+ {
+ List<Boolean> list = new ArrayList<Boolean>();
+ reader.readBoolList(list);
+ value = list;
+ break;
+ }
+ case UINT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readUInt32List(list);
+ value = list;
+ break;
+ }
+ case SFIXED32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readSFixed32List(list);
+ value = list;
+ break;
+ }
+ case SFIXED64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readSFixed64List(list);
+ value = list;
+ break;
+ }
+ case SINT32:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readSInt32List(list);
+ value = list;
+ break;
+ }
+ case SINT64:
+ {
+ List<Long> list = new ArrayList<Long>();
+ reader.readSInt64List(list);
+ value = list;
+ break;
+ }
+ case ENUM:
+ {
+ List<Integer> list = new ArrayList<Integer>();
+ reader.readEnumList(list);
+ unknownFields =
+ SchemaUtil.filterUnknownEnumList(
+ fieldNumber,
+ list,
+ extension.descriptor.getEnumType(),
+ unknownFields,
+ unknownFieldSchema);
+ value = list;
+ break;
+ }
+ default:
+ throw new IllegalStateException(
+ "Type cannot be packed: " + extension.descriptor.getLiteType());
+ }
+ extensions.setField(extension.descriptor, value);
+ } else {
+ Object value = null;
+ // Enum is a special case becasue unknown enum values will be put into UnknownFieldSetLite.
+ if (extension.getLiteType() == WireFormat.FieldType.ENUM) {
+ int number = reader.readInt32();
+ Object enumValue = extension.descriptor.getEnumType().findValueByNumber(number);
+ if (enumValue == null) {
+ return SchemaUtil.storeUnknownEnum(
+ fieldNumber, number, unknownFields, unknownFieldSchema);
+ }
+ // Note, we store the integer value instead of the actual enum object in FieldSet.
+ // This is also different from full-runtime where we store EnumValueDescriptor.
+ value = number;
+ } else {
+ switch (extension.getLiteType()) {
+ case DOUBLE:
+ value = reader.readDouble();
+ break;
+ case FLOAT:
+ value = reader.readFloat();
+ break;
+ case INT64:
+ value = reader.readInt64();
+ break;
+ case UINT64:
+ value = reader.readUInt64();
+ break;
+ case INT32:
+ value = reader.readInt32();
+ break;
+ case FIXED64:
+ value = reader.readFixed64();
+ break;
+ case FIXED32:
+ value = reader.readFixed32();
+ break;
+ case BOOL:
+ value = reader.readBool();
+ break;
+ case BYTES:
+ value = reader.readBytes();
+ break;
+ case UINT32:
+ value = reader.readUInt32();
+ break;
+ case SFIXED32:
+ value = reader.readSFixed32();
+ break;
+ case SFIXED64:
+ value = reader.readSFixed64();
+ break;
+ case SINT32:
+ value = reader.readSInt32();
+ break;
+ case SINT64:
+ value = reader.readSInt64();
+ break;
+
+ case STRING:
+ value = reader.readString();
+ break;
+ case GROUP:
+ value =
+ reader.readGroup(
+ extension.getMessageDefaultInstance().getClass(), extensionRegistry);
+ break;
+
+ case MESSAGE:
+ value =
+ reader.readMessage(
+ extension.getMessageDefaultInstance().getClass(), extensionRegistry);
+ break;
+
+ case ENUM:
+ throw new IllegalStateException("Shouldn't reach here.");
+ }
+ }
+ if (extension.isRepeated()) {
+ extensions.addRepeatedField(extension.descriptor, value);
+ } else {
+ switch (extension.getLiteType()) {
+ case MESSAGE:
+ case GROUP:
+ Object oldValue = extensions.getField(extension.descriptor);
+ if (oldValue != null) {
+ value = Internal.mergeMessage(oldValue, value);
+ }
+ break;
+ default:
+ break;
+ }
+ extensions.setField(extension.descriptor, value);
+ }
+ }
+ return unknownFields;
+ }
+
+ @Override
+ int extensionNumber(Map.Entry<?, ?> extension) {
+ GeneratedMessageLite.ExtensionDescriptor descriptor =
+ (GeneratedMessageLite.ExtensionDescriptor) extension.getKey();
+ return descriptor.getNumber();
+ }
+
+ @Override
+ void serializeExtension(Writer writer, Map.Entry<?, ?> extension) throws IOException {
+ GeneratedMessageLite.ExtensionDescriptor descriptor =
+ (GeneratedMessageLite.ExtensionDescriptor) extension.getKey();
+ if (descriptor.isRepeated()) {
+ switch (descriptor.getLiteType()) {
+ case DOUBLE:
+ SchemaUtil.writeDoubleList(
+ descriptor.getNumber(),
+ (List<Double>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FLOAT:
+ SchemaUtil.writeFloatList(
+ descriptor.getNumber(),
+ (List<Float>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case INT64:
+ SchemaUtil.writeInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case UINT64:
+ SchemaUtil.writeUInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case INT32:
+ SchemaUtil.writeInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FIXED64:
+ SchemaUtil.writeFixed64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case FIXED32:
+ SchemaUtil.writeFixed32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case BOOL:
+ SchemaUtil.writeBoolList(
+ descriptor.getNumber(),
+ (List<Boolean>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case BYTES:
+ SchemaUtil.writeBytesList(
+ descriptor.getNumber(), (List<ByteString>) extension.getValue(), writer);
+ break;
+ case UINT32:
+ SchemaUtil.writeUInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SFIXED32:
+ SchemaUtil.writeSFixed32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SFIXED64:
+ SchemaUtil.writeSFixed64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SINT32:
+ SchemaUtil.writeSInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case SINT64:
+ SchemaUtil.writeSInt64List(
+ descriptor.getNumber(),
+ (List<Long>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case ENUM:
+ SchemaUtil.writeInt32List(
+ descriptor.getNumber(),
+ (List<Integer>) extension.getValue(),
+ writer,
+ descriptor.isPacked());
+ break;
+ case STRING:
+ SchemaUtil.writeStringList(
+ descriptor.getNumber(), (List<String>) extension.getValue(), writer);
+ break;
+ case GROUP:
+ {
+ List<?> data = (List<?>) extension.getValue();
+ if (data != null && !data.isEmpty()) {
+ SchemaUtil.writeGroupList(
+ descriptor.getNumber(),
+ (List<?>) extension.getValue(),
+ writer,
+ Protobuf.getInstance().schemaFor(data.get(0).getClass()));
+ }
+ }
+ break;
+ case MESSAGE:
+ {
+ List<?> data = (List<?>) extension.getValue();
+ if (data != null && !data.isEmpty()) {
+ SchemaUtil.writeMessageList(
+ descriptor.getNumber(),
+ (List<?>) extension.getValue(),
+ writer,
+ Protobuf.getInstance().schemaFor(data.get(0).getClass()));
+ }
+ }
+ break;
+ }
+ } else {
+ switch (descriptor.getLiteType()) {
+ case DOUBLE:
+ writer.writeDouble(descriptor.getNumber(), (Double) extension.getValue());
+ break;
+ case FLOAT:
+ writer.writeFloat(descriptor.getNumber(), (Float) extension.getValue());
+ break;
+ case INT64:
+ writer.writeInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case UINT64:
+ writer.writeUInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case INT32:
+ writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case FIXED64:
+ writer.writeFixed64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case FIXED32:
+ writer.writeFixed32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case BOOL:
+ writer.writeBool(descriptor.getNumber(), (Boolean) extension.getValue());
+ break;
+ case BYTES:
+ writer.writeBytes(descriptor.getNumber(), (ByteString) extension.getValue());
+ break;
+ case UINT32:
+ writer.writeUInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SFIXED32:
+ writer.writeSFixed32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SFIXED64:
+ writer.writeSFixed64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case SINT32:
+ writer.writeSInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case SINT64:
+ writer.writeSInt64(descriptor.getNumber(), (Long) extension.getValue());
+ break;
+ case ENUM:
+ writer.writeInt32(descriptor.getNumber(), (Integer) extension.getValue());
+ break;
+ case STRING:
+ writer.writeString(descriptor.getNumber(), (String) extension.getValue());
+ break;
+ case GROUP:
+ writer.writeGroup(
+ descriptor.getNumber(),
+ extension.getValue(),
+ Protobuf.getInstance().schemaFor(extension.getValue().getClass()));
+ break;
+ case MESSAGE:
+ writer.writeMessage(
+ descriptor.getNumber(),
+ extension.getValue(),
+ Protobuf.getInstance().schemaFor(extension.getValue().getClass()));
+ break;
+ }
+ }
+ }
+
+ @Override
+ Object findExtensionByNumber(
+ ExtensionRegistryLite extensionRegistry, MessageLite defaultInstance, int number) {
+ return extensionRegistry.findLiteExtensionByNumber(defaultInstance, number);
+ }
+
+ @Override
+ void parseLengthPrefixedMessageSetItem(
+ Reader reader,
+ Object extensionObject,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<ExtensionDescriptor> extensions)
+ throws IOException {
+ GeneratedMessageLite.GeneratedExtension<?, ?> extension =
+ (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject;
+ Object value =
+ reader.readMessage(extension.getMessageDefaultInstance().getClass(), extensionRegistry);
+ extensions.setField(extension.descriptor, value);
+ }
+
+ @Override
+ void parseMessageSetItem(
+ ByteString data,
+ Object extensionObject,
+ ExtensionRegistryLite extensionRegistry,
+ FieldSet<ExtensionDescriptor> extensions)
+ throws IOException {
+ GeneratedMessageLite.GeneratedExtension<?, ?> extension =
+ (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionObject;
+ Object value = extension.getMessageDefaultInstance().newBuilderForType().buildPartial();
+
+ Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(data.toByteArray()), true);
+
+ Protobuf.getInstance().mergeFrom(value, reader, extensionRegistry);
+ extensions.setField(extension.descriptor, value);
+
+ if (reader.getFieldNumber() != Reader.READ_DONE) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java
new file mode 100755
index 000000000..46ce327d1
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java
@@ -0,0 +1,56 @@
+// 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;
+
+final class ExtensionSchemas {
+ private static final ExtensionSchema<?> LITE_SCHEMA = new ExtensionSchemaLite();
+ private static final ExtensionSchema<?> FULL_SCHEMA = loadSchemaForFullRuntime();
+
+ private static ExtensionSchema<?> loadSchemaForFullRuntime() {
+ try {
+ Class<?> clazz = Class.forName("com.google.protobuf.ExtensionSchemaFull");
+ return (ExtensionSchema) clazz.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ static ExtensionSchema<?> lite() {
+ return LITE_SCHEMA;
+ }
+
+ static ExtensionSchema<?> full() {
+ if (FULL_SCHEMA == null) {
+ throw new IllegalStateException("Protobuf runtime is not correctly loaded.");
+ }
+ return FULL_SCHEMA;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/FieldInfo.java b/java/core/src/main/java/com/google/protobuf/FieldInfo.java
new file mode 100755
index 000000000..71a307a89
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/FieldInfo.java
@@ -0,0 +1,577 @@
+// 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 com.google.protobuf.Internal.EnumVerifier;
+import java.lang.reflect.Field;
+
+/** Information for a single field in a protobuf message class. */
+@ExperimentalApi
+final class FieldInfo implements Comparable<FieldInfo> {
+ private final Field field;
+ private final FieldType type;
+ private final Class<?> messageClass; // The message type for repeated message fields.
+ private final int fieldNumber;
+ private final Field presenceField;
+ private final int presenceMask;
+ private final boolean required;
+ private final boolean enforceUtf8;
+ private final OneofInfo oneof;
+ private final Field cachedSizeField;
+ /**
+ * The actual type stored in the oneof value for this field. Since the oneof value is an {@link
+ * Object}, primitives will store their boxed type. Only valid in conjunction with {@link #oneof}
+ * (both must be either null or non-null.
+ */
+ private final Class<?> oneofStoredType;
+
+ // TODO(liujisi): make map default entry lazy?
+ private final Object mapDefaultEntry;
+
+ private final EnumVerifier enumVerifier;
+
+ /** Constructs a new descriptor for a field. */
+ public static FieldInfo forField(
+ Field field, int fieldNumber, FieldType fieldType, boolean enforceUtf8) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ checkNotNull(fieldType, "fieldType");
+ if (fieldType == FieldType.MESSAGE_LIST || fieldType == FieldType.GROUP_LIST) {
+ throw new IllegalStateException("Shouldn't be called for repeated message fields.");
+ }
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ enforceUtf8,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ /* enumVerifier= */ null,
+ /* cachedSizeField= */ null);
+ }
+
+ /** Constructs a new descriptor for a packed field. */
+ public static FieldInfo forPackedField(
+ Field field, int fieldNumber, FieldType fieldType, Field cachedSizeField) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ checkNotNull(fieldType, "fieldType");
+ if (fieldType == FieldType.MESSAGE_LIST || fieldType == FieldType.GROUP_LIST) {
+ throw new IllegalStateException("Shouldn't be called for repeated message fields.");
+ }
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ /* enforceUtf8= */ false,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ /* enumVerifier= */ null,
+ cachedSizeField);
+ }
+
+ /** Constructs a new descriptor for a repeated message field. */
+ public static FieldInfo forRepeatedMessageField(
+ Field field, int fieldNumber, FieldType fieldType, Class<?> messageClass) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ checkNotNull(fieldType, "fieldType");
+ checkNotNull(messageClass, "messageClass");
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ messageClass,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ /* enforceUtf8= */ false,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ /* enumVerifier= */ null,
+ /* cachedSizeField= */ null);
+ }
+
+ public static FieldInfo forFieldWithEnumVerifier(
+ Field field, int fieldNumber, FieldType fieldType, EnumVerifier enumVerifier) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ /* enforceUtf8= */ false,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ enumVerifier,
+ /* cachedSizeField= */ null);
+ }
+
+ public static FieldInfo forPackedFieldWithEnumVerifier(
+ Field field,
+ int fieldNumber,
+ FieldType fieldType,
+ EnumVerifier enumVerifier,
+ Field cachedSizeField) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ /* enforceUtf8= */ false,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ enumVerifier,
+ cachedSizeField);
+ }
+
+ /** Constructor for a proto2 optional field. */
+ public static FieldInfo forProto2OptionalField(
+ Field field,
+ int fieldNumber,
+ FieldType fieldType,
+ Field presenceField,
+ int presenceMask,
+ boolean enforceUtf8,
+ EnumVerifier enumVerifier) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ checkNotNull(fieldType, "fieldType");
+ checkNotNull(presenceField, "presenceField");
+ if (presenceField != null && !isExactlyOneBitSet(presenceMask)) {
+ throw new IllegalArgumentException(
+ "presenceMask must have exactly one bit set: " + presenceMask);
+ }
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ presenceField,
+ presenceMask,
+ /* required= */ false,
+ enforceUtf8,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ enumVerifier,
+ /* cachedSizeField= */ null);
+ }
+
+ /**
+ * Constructor for a field that is part of a oneof.
+ *
+ * @param fieldNumber the unique field number for this field within the message.
+ * @param fieldType the type of the field (must be non-null).
+ * @param oneof the oneof for which this field is associated (must be non-null).
+ * @param oneofStoredType the actual type stored in the oneof value for this field. Since the
+ * oneof value is an {@link Object}, primitives will store their boxed type. Must be non-null.
+ * @param enforceUtf8 Only used for string fields. If {@code true}, will enforce UTF-8 on a string
+ * field.
+ * @return the {@link FieldInfo} describing this field.
+ */
+ public static FieldInfo forOneofMemberField(
+ int fieldNumber,
+ FieldType fieldType,
+ OneofInfo oneof,
+ Class<?> oneofStoredType,
+ boolean enforceUtf8,
+ EnumVerifier enumVerifier) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(fieldType, "fieldType");
+ checkNotNull(oneof, "oneof");
+ checkNotNull(oneofStoredType, "oneofStoredType");
+ if (!fieldType.isScalar()) {
+ throw new IllegalArgumentException(
+ "Oneof is only supported for scalar fields. Field "
+ + fieldNumber
+ + " is of type "
+ + fieldType);
+ }
+ return new FieldInfo(
+ /* field= */ null,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ enforceUtf8,
+ oneof,
+ oneofStoredType,
+ /* mapDefaultEntry= */ null,
+ enumVerifier,
+ /* cachedSizeField= */ null);
+ }
+
+ private static void checkFieldNumber(int fieldNumber) {
+ if (fieldNumber <= 0) {
+ throw new IllegalArgumentException("fieldNumber must be positive: " + fieldNumber);
+ }
+ }
+
+ /** Constructor for a proto2 required field. */
+ public static FieldInfo forProto2RequiredField(
+ Field field,
+ int fieldNumber,
+ FieldType fieldType,
+ Field presenceField,
+ int presenceMask,
+ boolean enforceUtf8,
+ EnumVerifier enumVerifier) {
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ checkNotNull(fieldType, "fieldType");
+ checkNotNull(presenceField, "presenceField");
+ if (presenceField != null && !isExactlyOneBitSet(presenceMask)) {
+ throw new IllegalArgumentException(
+ "presenceMask must have exactly one bit set: " + presenceMask);
+ }
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ fieldType,
+ /* messageClass= */ null,
+ presenceField,
+ presenceMask,
+ /* required= */ true,
+ enforceUtf8,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ /* mapDefaultEntry= */ null,
+ /* enumVerifier= */ enumVerifier,
+ /* cachedSizeField= */ null);
+ }
+
+ public static FieldInfo forMapField(
+ Field field, int fieldNumber, Object mapDefaultEntry, EnumVerifier enumVerifier) {
+ checkNotNull(mapDefaultEntry, "mapDefaultEntry");
+ checkFieldNumber(fieldNumber);
+ checkNotNull(field, "field");
+ return new FieldInfo(
+ field,
+ fieldNumber,
+ FieldType.MAP,
+ /* messageClass= */ null,
+ /* presenceField= */ null,
+ /* presenceMask= */ 0,
+ /* required= */ false,
+ /* enforceUtf8= */ true,
+ /* oneof= */ null,
+ /* oneofStoredType= */ null,
+ mapDefaultEntry,
+ enumVerifier,
+ /* cachedSizeField= */ null);
+ }
+
+ private FieldInfo(
+ Field field,
+ int fieldNumber,
+ FieldType type,
+ Class<?> messageClass,
+ Field presenceField,
+ int presenceMask,
+ boolean required,
+ boolean enforceUtf8,
+ OneofInfo oneof,
+ Class<?> oneofStoredType,
+ Object mapDefaultEntry,
+ EnumVerifier enumVerifier,
+ Field cachedSizeField) {
+ this.field = field;
+ this.type = type;
+ this.messageClass = messageClass;
+ this.fieldNumber = fieldNumber;
+ this.presenceField = presenceField;
+ this.presenceMask = presenceMask;
+ this.required = required;
+ this.enforceUtf8 = enforceUtf8;
+ this.oneof = oneof;
+ this.oneofStoredType = oneofStoredType;
+ this.mapDefaultEntry = mapDefaultEntry;
+ this.enumVerifier = enumVerifier;
+ this.cachedSizeField = cachedSizeField;
+ }
+
+ /** Gets the field number for the field. */
+ public int getFieldNumber() {
+ return fieldNumber;
+ }
+
+ /** Gets the subject {@link Field} of this descriptor. */
+ public Field getField() {
+ return field;
+ }
+
+ /** Gets the type information for the field. */
+ public FieldType getType() {
+ return type;
+ }
+
+ /** Gets the oneof for which this field is a member, or {@code null} if not part of a oneof. */
+ public OneofInfo getOneof() {
+ return oneof;
+ }
+
+ /**
+ * Gets the actual type stored in the oneof value by this field. Since the oneof value is an
+ * {@link Object}, primitives will store their boxed type. For non-oneof fields, this will always
+ * be {@code null}.
+ */
+ public Class<?> getOneofStoredType() {
+ return oneofStoredType;
+ }
+
+ /** Gets the {@code EnumVerifier} if the field is an enum field. */
+ public EnumVerifier getEnumVerifier() {
+ return enumVerifier;
+ }
+
+ @Override
+ public int compareTo(FieldInfo o) {
+ return fieldNumber - o.fieldNumber;
+ }
+
+ /**
+ * For repeated message fields, returns the message type of the field. For other fields, returns
+ * {@code null}.
+ */
+ public Class<?> getListElementType() {
+ return messageClass;
+ }
+
+ /** Gets the presence bit field. Only valid for unary fields. For lists, returns {@code null}. */
+ public Field getPresenceField() {
+ return presenceField;
+ }
+
+ public Object getMapDefaultEntry() {
+ return mapDefaultEntry;
+ }
+
+ /**
+ * If {@link #getPresenceField()} is non-{@code null}, returns the mask used to identify the
+ * presence bit for this field in the message.
+ */
+ public int getPresenceMask() {
+ return presenceMask;
+ }
+
+ /** Whether this is a required field. */
+ public boolean isRequired() {
+ return required;
+ }
+
+ /**
+ * Whether a UTF-8 should be enforced on string fields. Only applies to strings and string lists.
+ */
+ public boolean isEnforceUtf8() {
+ return enforceUtf8;
+ }
+
+ public Field getCachedSizeField() {
+ return cachedSizeField;
+ }
+
+ /**
+ * For singular or repeated message fields, returns the message type. For other fields, returns
+ * {@code null}.
+ */
+ public Class<?> getMessageFieldClass() {
+ switch (type) {
+ case MESSAGE:
+ case GROUP:
+ return field != null ? field.getType() : oneofStoredType;
+ case MESSAGE_LIST:
+ case GROUP_LIST:
+ return messageClass;
+ default:
+ return null;
+ }
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /** A builder for {@link FieldInfo} instances. */
+ public static final class Builder {
+ private Field field;
+ private FieldType type;
+ private int fieldNumber;
+ private Field presenceField;
+ private int presenceMask;
+ private boolean required;
+ private boolean enforceUtf8;
+ private OneofInfo oneof;
+ private Class<?> oneofStoredType;
+ private Object mapDefaultEntry;
+ private EnumVerifier enumVerifier;
+ private Field cachedSizeField;
+
+ private Builder() {}
+
+ /**
+ * Specifies the actual field on the message represented by this field. This should not be
+ * called for oneof member fields.
+ */
+ public Builder withField(Field field) {
+ if (oneof != null) {
+ throw new IllegalStateException("Cannot set field when building a oneof.");
+ }
+ this.field = field;
+ return this;
+ }
+
+ /** Specifies the type of this field. */
+ public Builder withType(FieldType type) {
+ this.type = type;
+ return this;
+ }
+
+ /** Specifies the unique field number for this field within the message. */
+ public Builder withFieldNumber(int fieldNumber) {
+ this.fieldNumber = fieldNumber;
+ return this;
+ }
+
+ /** Specifies proto2 presence information. This should not be called for oneof fields. */
+ public Builder withPresence(Field presenceField, int presenceMask) {
+ this.presenceField = checkNotNull(presenceField, "presenceField");
+ this.presenceMask = presenceMask;
+ return this;
+ }
+
+ /**
+ * Sets the information for building a oneof member field. This is incompatible with {@link
+ * #withField(Field)} and {@link #withPresence(Field, int)}.
+ *
+ * @param oneof the oneof for which this field is associated.
+ * @param oneofStoredType the actual type stored in the oneof value for this field. Since the
+ * oneof value is an {@link Object}, primitives will store their boxed type.
+ */
+ public Builder withOneof(OneofInfo oneof, Class<?> oneofStoredType) {
+ if (field != null || presenceField != null) {
+ throw new IllegalStateException(
+ "Cannot set oneof when field or presenceField have been provided");
+ }
+ this.oneof = oneof;
+ this.oneofStoredType = oneofStoredType;
+ return this;
+ }
+
+ public Builder withRequired(boolean required) {
+ this.required = required;
+ return this;
+ }
+
+ public Builder withMapDefaultEntry(Object mapDefaultEntry) {
+ this.mapDefaultEntry = mapDefaultEntry;
+ return this;
+ }
+
+ public Builder withEnforceUtf8(boolean enforceUtf8) {
+ this.enforceUtf8 = enforceUtf8;
+ return this;
+ }
+
+ public Builder withEnumVerifier(EnumVerifier enumVerifier) {
+ this.enumVerifier = enumVerifier;
+ return this;
+ }
+
+ public Builder withCachedSizeField(Field cachedSizeField) {
+ this.cachedSizeField = cachedSizeField;
+ return this;
+ }
+
+ public FieldInfo build() {
+ if (oneof != null) {
+ return forOneofMemberField(
+ fieldNumber, type, oneof, oneofStoredType, enforceUtf8, enumVerifier);
+ }
+ if (mapDefaultEntry != null) {
+ return forMapField(field, fieldNumber, mapDefaultEntry, enumVerifier);
+ }
+ if (presenceField != null) {
+ if (required) {
+ return forProto2RequiredField(
+ field, fieldNumber, type, presenceField, presenceMask, enforceUtf8, enumVerifier);
+ } else {
+ return forProto2OptionalField(
+ field, fieldNumber, type, presenceField, presenceMask, enforceUtf8, enumVerifier);
+ }
+ }
+ if (enumVerifier != null) {
+ if (cachedSizeField == null) {
+ return forFieldWithEnumVerifier(field, fieldNumber, type, enumVerifier);
+ } else {
+ return forPackedFieldWithEnumVerifier(
+ field, fieldNumber, type, enumVerifier, cachedSizeField);
+ }
+ } else {
+ if (cachedSizeField == null) {
+ return forField(field, fieldNumber, type, enforceUtf8);
+ } else {
+ return forPackedField(field, fieldNumber, type, cachedSizeField);
+ }
+ }
+ }
+ }
+
+ private static boolean isExactlyOneBitSet(int value) {
+ return value != 0 && (value & (value - 1)) == 0;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/FieldSet.java b/java/core/src/main/java/com/google/protobuf/FieldSet.java
index 40a37625a..ddfd0e560 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -218,6 +218,17 @@ final class FieldSet<
return fields.entrySet().iterator();
}
+ /**
+ * Get an iterator over the fields in the map in descending (i.e. reverse) order. This iterator
+ * should not be leaked out of the protobuf library as it is not protected from mutation when
+ * fields is not immutable.
+ */
+ Iterator<Map.Entry<FieldDescriptorType, Object>> descendingIterator() {
+ if (hasLazyField) {
+ return new LazyIterator<FieldDescriptorType>(fields.descendingEntrySet().iterator());
+ }
+ return fields.descendingEntrySet().iterator();
+ }
/** Useful for implementing {@link Message#hasField(Descriptors.FieldDescriptor)}. */
public boolean hasField(final FieldDescriptorType descriptor) {
diff --git a/java/core/src/main/java/com/google/protobuf/FieldType.java b/java/core/src/main/java/com/google/protobuf/FieldType.java
new file mode 100755
index 000000000..1b8f9e5da
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/FieldType.java
@@ -0,0 +1,346 @@
+// 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.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
+
+/** Enumeration identifying all relevant type information for a protobuf field. */
+@ExperimentalApi
+public enum FieldType {
+ DOUBLE(0, Collection.SCALAR, JavaType.DOUBLE),
+ FLOAT(1, Collection.SCALAR, JavaType.FLOAT),
+ INT64(2, Collection.SCALAR, JavaType.LONG),
+ UINT64(3, Collection.SCALAR, JavaType.LONG),
+ INT32(4, Collection.SCALAR, JavaType.INT),
+ FIXED64(5, Collection.SCALAR, JavaType.LONG),
+ FIXED32(6, Collection.SCALAR, JavaType.INT),
+ BOOL(7, Collection.SCALAR, JavaType.BOOLEAN),
+ STRING(8, Collection.SCALAR, JavaType.STRING),
+ MESSAGE(9, Collection.SCALAR, JavaType.MESSAGE),
+ BYTES(10, Collection.SCALAR, JavaType.BYTE_STRING),
+ UINT32(11, Collection.SCALAR, JavaType.INT),
+ ENUM(12, Collection.SCALAR, JavaType.ENUM),
+ SFIXED32(13, Collection.SCALAR, JavaType.INT),
+ SFIXED64(14, Collection.SCALAR, JavaType.LONG),
+ SINT32(15, Collection.SCALAR, JavaType.INT),
+ SINT64(16, Collection.SCALAR, JavaType.LONG),
+ GROUP(17, Collection.SCALAR, JavaType.MESSAGE),
+ DOUBLE_LIST(18, Collection.VECTOR, JavaType.DOUBLE),
+ FLOAT_LIST(19, Collection.VECTOR, JavaType.FLOAT),
+ INT64_LIST(20, Collection.VECTOR, JavaType.LONG),
+ UINT64_LIST(21, Collection.VECTOR, JavaType.LONG),
+ INT32_LIST(22, Collection.VECTOR, JavaType.INT),
+ FIXED64_LIST(23, Collection.VECTOR, JavaType.LONG),
+ FIXED32_LIST(24, Collection.VECTOR, JavaType.INT),
+ BOOL_LIST(25, Collection.VECTOR, JavaType.BOOLEAN),
+ STRING_LIST(26, Collection.VECTOR, JavaType.STRING),
+ MESSAGE_LIST(27, Collection.VECTOR, JavaType.MESSAGE),
+ BYTES_LIST(28, Collection.VECTOR, JavaType.BYTE_STRING),
+ UINT32_LIST(29, Collection.VECTOR, JavaType.INT),
+ ENUM_LIST(30, Collection.VECTOR, JavaType.ENUM),
+ SFIXED32_LIST(31, Collection.VECTOR, JavaType.INT),
+ SFIXED64_LIST(32, Collection.VECTOR, JavaType.LONG),
+ SINT32_LIST(33, Collection.VECTOR, JavaType.INT),
+ SINT64_LIST(34, Collection.VECTOR, JavaType.LONG),
+ DOUBLE_LIST_PACKED(35, Collection.PACKED_VECTOR, JavaType.DOUBLE),
+ FLOAT_LIST_PACKED(36, Collection.PACKED_VECTOR, JavaType.FLOAT),
+ INT64_LIST_PACKED(37, Collection.PACKED_VECTOR, JavaType.LONG),
+ UINT64_LIST_PACKED(38, Collection.PACKED_VECTOR, JavaType.LONG),
+ INT32_LIST_PACKED(39, Collection.PACKED_VECTOR, JavaType.INT),
+ FIXED64_LIST_PACKED(40, Collection.PACKED_VECTOR, JavaType.LONG),
+ FIXED32_LIST_PACKED(41, Collection.PACKED_VECTOR, JavaType.INT),
+ BOOL_LIST_PACKED(42, Collection.PACKED_VECTOR, JavaType.BOOLEAN),
+ UINT32_LIST_PACKED(43, Collection.PACKED_VECTOR, JavaType.INT),
+ ENUM_LIST_PACKED(44, Collection.PACKED_VECTOR, JavaType.ENUM),
+ SFIXED32_LIST_PACKED(45, Collection.PACKED_VECTOR, JavaType.INT),
+ SFIXED64_LIST_PACKED(46, Collection.PACKED_VECTOR, JavaType.LONG),
+ SINT32_LIST_PACKED(47, Collection.PACKED_VECTOR, JavaType.INT),
+ SINT64_LIST_PACKED(48, Collection.PACKED_VECTOR, JavaType.LONG),
+ GROUP_LIST(49, Collection.VECTOR, JavaType.MESSAGE),
+ MAP(50, Collection.MAP, JavaType.VOID);
+
+ private final JavaType javaType;
+ private final int id;
+ private final Collection collection;
+ private final Class<?> elementType;
+ private final boolean primitiveScalar;
+
+ FieldType(int id, Collection collection, JavaType javaType) {
+ this.id = id;
+ this.collection = collection;
+ this.javaType = javaType;
+
+ switch (collection) {
+ case MAP:
+ elementType = javaType.getBoxedType();
+ break;
+ case VECTOR:
+ elementType = javaType.getBoxedType();
+ break;
+ case SCALAR:
+ default:
+ elementType = null;
+ break;
+ }
+
+ boolean primitiveScalar = false;
+ if (collection == Collection.SCALAR) {
+ switch (javaType) {
+ case BYTE_STRING:
+ case MESSAGE:
+ case STRING:
+ break;
+ default:
+ primitiveScalar = true;
+ break;
+ }
+ }
+ this.primitiveScalar = primitiveScalar;
+ }
+
+ /** A reliable unique identifier for this type. */
+ public int id() {
+ return id;
+ }
+
+ /**
+ * Gets the {@link JavaType} for this field. For lists, this identifies the type of the elements
+ * contained within the list.
+ */
+ public JavaType getJavaType() {
+ return javaType;
+ }
+
+ /** Indicates whether a list field should be represented on the wire in packed form. */
+ public boolean isPacked() {
+ return Collection.PACKED_VECTOR.equals(collection);
+ }
+
+ /**
+ * Indicates whether this field type represents a primitive scalar value. If this is {@code true},
+ * then {@link #isScalar()} will also be {@code true}.
+ */
+ public boolean isPrimitiveScalar() {
+ return primitiveScalar;
+ }
+
+ /** Indicates whether this field type represents a scalar value. */
+ public boolean isScalar() {
+ return collection == Collection.SCALAR;
+ }
+
+ /** Indicates whether this field represents a list of values. */
+ public boolean isList() {
+ return collection.isList();
+ }
+
+ /** Indicates whether this field represents a map. */
+ public boolean isMap() {
+ return collection == Collection.MAP;
+ }
+
+ /** Indicates whether or not this {@link FieldType} can be applied to the given {@link Field}. */
+ public boolean isValidForField(Field field) {
+ if (Collection.VECTOR.equals(collection)) {
+ return isValidForList(field);
+ } else {
+ return javaType.getType().isAssignableFrom(field.getType());
+ }
+ }
+
+ private boolean isValidForList(Field field) {
+ Class<?> clazz = field.getType();
+ if (!javaType.getType().isAssignableFrom(clazz)) {
+ // The field isn't a List type.
+ return false;
+ }
+ Type[] types = EMPTY_TYPES;
+ Type genericType = field.getGenericType();
+ if (genericType instanceof ParameterizedType) {
+ types = ((ParameterizedType) field.getGenericType()).getActualTypeArguments();
+ }
+ Type listParameter = getListParameter(clazz, types);
+ if (!(listParameter instanceof Class)) {
+ // It's a wildcard, we should allow anything in the list.
+ return true;
+ }
+ return elementType.isAssignableFrom((Class<?>) listParameter);
+ }
+
+ /**
+ * Looks up the appropriate {@link FieldType} by it's identifier.
+ *
+ * @return the {@link FieldType} or {@code null} if not found.
+ */
+ /* @Nullable */
+ public static FieldType forId(int id) {
+ if (id < 0 || id >= VALUES.length) {
+ return null;
+ }
+ return VALUES[id];
+ }
+
+ private static final FieldType[] VALUES;
+ private static final Type[] EMPTY_TYPES = new Type[0];
+
+ static {
+ FieldType[] values = values();
+ VALUES = new FieldType[values.length];
+ for (FieldType type : values) {
+ VALUES[type.id] = type;
+ }
+ }
+
+ /**
+ * Given a class, finds a generic super class or interface that extends {@link List}.
+ *
+ * @return the generic super class/interface, or {@code null} if not found.
+ */
+ /* @Nullable */
+ private static Type getGenericSuperList(Class<?> clazz) {
+ // First look at interfaces.
+ Type[] genericInterfaces = clazz.getGenericInterfaces();
+ for (Type genericInterface : genericInterfaces) {
+ if (genericInterface instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
+ Class<?> rawType = (Class<?>) parameterizedType.getRawType();
+ if (List.class.isAssignableFrom(rawType)) {
+ return genericInterface;
+ }
+ }
+ }
+
+ // Try the subclass
+ Type type = clazz.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ Class<?> rawType = (Class<?>) parameterizedType.getRawType();
+ if (List.class.isAssignableFrom(rawType)) {
+ return type;
+ }
+ }
+
+ // No super class/interface extends List.
+ return null;
+ }
+
+ /**
+ * Inspects the inheritance hierarchy for the given class and finds the generic type parameter for
+ * {@link List}.
+ *
+ * @param clazz the class to begin the search.
+ * @param realTypes the array of actual type parameters for {@code clazz}. These will be used to
+ * substitute generic parameters up the inheritance hierarchy. If {@code clazz} does not have
+ * any generic parameters, this list should be empty.
+ * @return the {@link List} parameter.
+ */
+ private static Type getListParameter(Class<?> clazz, Type[] realTypes) {
+ top:
+ while (clazz != List.class) {
+ // First look at generic subclass and interfaces.
+ Type genericType = getGenericSuperList(clazz);
+ if (genericType instanceof ParameterizedType) {
+ // Replace any generic parameters with the real values.
+ ParameterizedType parameterizedType = (ParameterizedType) genericType;
+ Type[] superArgs = parameterizedType.getActualTypeArguments();
+ for (int i = 0; i < superArgs.length; ++i) {
+ Type superArg = superArgs[i];
+ if (superArg instanceof TypeVariable) {
+ // Get the type variables for this class so that we can match them to the variables
+ // used on the super class.
+ TypeVariable<?>[] clazzParams = clazz.getTypeParameters();
+ if (realTypes.length != clazzParams.length) {
+ throw new RuntimeException("Type array mismatch");
+ }
+
+ // Replace the variable parameter with the real type.
+ boolean foundReplacement = false;
+ for (int j = 0; j < clazzParams.length; ++j) {
+ if (superArg == clazzParams[j]) {
+ Type realType = realTypes[j];
+ superArgs[i] = realType;
+ foundReplacement = true;
+ break;
+ }
+ }
+ if (!foundReplacement) {
+ throw new RuntimeException("Unable to find replacement for " + superArg);
+ }
+ }
+ }
+
+ Class<?> parent = (Class<?>) parameterizedType.getRawType();
+
+ realTypes = superArgs;
+ clazz = parent;
+ continue;
+ }
+
+ // None of the parameterized types inherit List. Just continue up the inheritance hierarchy
+ // toward the List interface until we can identify the parameters.
+ realTypes = EMPTY_TYPES;
+ for (Class<?> iface : clazz.getInterfaces()) {
+ if (List.class.isAssignableFrom(iface)) {
+ clazz = iface;
+ continue top;
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+
+ if (realTypes.length != 1) {
+ throw new RuntimeException("Unable to identify parameter type for List<T>");
+ }
+ return realTypes[0];
+ }
+
+ enum Collection {
+ SCALAR(false),
+ VECTOR(true),
+ PACKED_VECTOR(true),
+ MAP(false);
+
+ private final boolean isList;
+
+ Collection(boolean isList) {
+ this.isList = isList;
+ }
+
+ /** @return the isList */
+ public boolean isList() {
+ return isList;
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java
new file mode 100755
index 000000000..3e3efb929
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.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;
+
+/** A factory for message info that is generated into the message itself. */
+@ExperimentalApi
+class GeneratedMessageInfoFactory implements MessageInfoFactory {
+
+ private static final GeneratedMessageInfoFactory instance = new GeneratedMessageInfoFactory();
+
+ // Disallow construction - it's a singleton.
+ private GeneratedMessageInfoFactory() {}
+
+ public static GeneratedMessageInfoFactory getInstance() {
+ return instance;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> messageType) {
+ return GeneratedMessageLite.class.isAssignableFrom(messageType);
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> messageType) {
+ if (!GeneratedMessageLite.class.isAssignableFrom(messageType)) {
+ throw new IllegalArgumentException("Unsupported message type: " + messageType.getName());
+ }
+
+ try {
+ return (MessageInfo) GeneratedMessageLite.getDefaultInstance(
+ messageType.asSubclass(GeneratedMessageLite.class))
+ .buildMessageInfo();
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to get message info for " + messageType.getName(), e);
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 619ef0999..61cbed60a 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -61,12 +61,6 @@ public abstract class GeneratedMessageLite<
MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
extends AbstractMessageLite<MessageType, BuilderType> {
- // BEGIN REGULAR
- static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = false;
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // static final boolean ENABLE_EXPERIMENTAL_RUNTIME_AT_BUILD_TIME = true;
- // END EXPERIMENTAL
/** For use by generated code only. Lazily initialized to reduce allocations. */
protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
@@ -115,32 +109,10 @@ public abstract class GeneratedMessageLite<
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
- // BEGIN EXPERIMENTAL
- // memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this);
- // return memoizedHashCode;
- // END EXPERIMENTAL
- // BEGIN REGULAR
- HashCodeVisitor visitor = new HashCodeVisitor();
- visit(visitor, (MessageType) this);
- memoizedHashCode = visitor.hashCode;
+ memoizedHashCode = Protobuf.getInstance().schemaFor(this).hashCode(this);
return memoizedHashCode;
- // END REGULAR
}
- // BEGIN REGULAR
- @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;
- }
- // END REGULAR
-
@SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
@Override
public boolean equals(Object other) {
@@ -152,36 +124,8 @@ public abstract class GeneratedMessageLite<
return false;
}
- // BEGIN EXPERIMENTAL
- // return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other);
- // END EXPERIMENTAL
- // BEGIN REGULAR
-
- try {
- visit(EqualsVisitor.INSTANCE, (MessageType) other);
- } catch (EqualsVisitor.NotEqualsException e) {
- return false;
- }
- return true;
- // END REGULAR
- }
-
- // BEGIN REGULAR
- /** 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;
+ return Protobuf.getInstance().schemaFor(this).equals(this, (MessageType) other);
}
- // END REGULAR
// 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
@@ -223,13 +167,7 @@ public abstract class GeneratedMessageLite<
/** Called by subclasses to complete parsing. For use by generated code only. */
protected void makeImmutable() {
- // BEGIN REGULAR
- dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
- unknownFields.makeImmutable();
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // Protobuf.getInstance().schemaFor(this).makeImmutable(this);
- // END EXPERIMENTAL
+ Protobuf.getInstance().schemaFor(this).makeImmutable(this);
}
protected final <
@@ -266,17 +204,12 @@ public abstract class GeneratedMessageLite<
* <p>For use by generated code only.
*/
public static enum MethodToInvoke {
- // BEGIN REGULAR
- IS_INITIALIZED,
- VISIT,
- MERGE_FROM_STREAM,
- MAKE_IMMUTABLE,
- // END REGULAR
// Rely on/modify instance state
GET_MEMOIZED_IS_INITIALIZED,
SET_MEMOIZED_IS_INITIALIZED,
// Rely on static state
+ BUILD_MESSAGE_INFO,
NEW_MUTABLE_INSTANCE,
NEW_BUILDER,
GET_DEFAULT_INSTANCE,
@@ -290,10 +223,6 @@ public abstract class GeneratedMessageLite<
* 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} returns {@code null} for false and the default instance for true.
@@ -303,9 +232,6 @@ public abstract class GeneratedMessageLite<
* <li>{@code SET_MEMOIZED_IS_INITIALIZED} sets the memoized {@code isInitilaized} byte value to
* 1 if the first parameter is not null, or to 0 if the first parameter is null.
* <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
@@ -325,13 +251,6 @@ public abstract class GeneratedMessageLite<
return dynamicMethod(method, null, null);
}
- // BEGIN REGULAR
- void visit(Visitor visitor, MessageType other) {
- dynamicMethod(MethodToInvoke.VISIT, visitor, other);
- unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields);
- }
- // END REGULAR
-
@Override
int getMemoizedSerializedSize() {
return memoizedSerializedSize;
@@ -342,7 +261,60 @@ public abstract class GeneratedMessageLite<
memoizedSerializedSize = size;
}
+ public void writeTo(CodedOutputStream output) throws IOException {
+ writeToInternal(output);
+ }
+
+ public int getSerializedSize() {
+ if (memoizedSerializedSize == -1) {
+ memoizedSerializedSize = getSerializedSizeInternal();
+ }
+ return memoizedSerializedSize;
+ }
+
+ /** Constructs a {@link MessageInfo} for this message type. */
+ Object buildMessageInfo() throws Exception {
+ return dynamicMethod(MethodToInvoke.BUILD_MESSAGE_INFO);
+ }
+
+ private static Map<Object, GeneratedMessageLite<?, ?>> defaultInstanceMap =
+ new ConcurrentHashMap<Object, GeneratedMessageLite<?, ?>>();
+
+ @SuppressWarnings("unchecked")
+ static <T extends GeneratedMessageLite<?, ?>> T getDefaultInstance(Class<T> clazz) {
+ T result = (T) defaultInstanceMap.get(clazz);
+ if (result == null) {
+ // Foo.class does not initialize the class so we need to force the initialization in order to
+ // get the default instance registered.
+ try {
+ Class.forName(clazz.getName(), true, clazz.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Class initialization cannot fail.", e);
+ }
+ result = (T) defaultInstanceMap.get(clazz);
+ }
+ if (result == null) {
+ // On some Samsung devices, this still doesn't return a valid value for some reason. We add a
+ // reflective fallback to keep the device running. See b/114675342.
+ result = (T) UnsafeUtil.allocateInstance(clazz).getDefaultInstanceForType();
+ // A sanity check to ensure that <clinit> was actually invoked.
+ if (result == null) {
+ throw new IllegalStateException();
+ }
+ defaultInstanceMap.put(clazz, result);
+ }
+ return result;
+ }
+
+ protected static <T extends GeneratedMessageLite<?, ?>> void registerDefaultInstance(
+ Class<T> clazz, T defaultInstance) {
+ defaultInstanceMap.put(clazz, defaultInstance);
+ }
+ protected static Object newMessageInfo(
+ MessageLite defaultInstance, String info, Object[] objects) {
+ return new RawMessageInfo(defaultInstance, info, objects);
+ }
/**
* Merge some unknown fields into the {@link UnknownFieldSetLite} for this message.
@@ -437,12 +409,7 @@ public abstract class GeneratedMessageLite<
}
private void mergeFromInstance(MessageType dest, MessageType src) {
- // BEGIN EXPERIMENTAL
- // Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src);
- // END EXPERIMENTAL
- // BEGIN REGULAR
- dest.visit(MergeFromVisitor.INSTANCE, src);
- // END REGULAR
+ Protobuf.getInstance().schemaFor(dest).mergeFrom(dest, src);
}
@Override
@@ -454,36 +421,26 @@ public abstract class GeneratedMessageLite<
public BuilderType mergeFrom(
byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- // BEGIN REGULAR
- return super.mergeFrom(input, offset, length, extensionRegistry);
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // copyOnWrite();
- // try {
- // Protobuf.getInstance().schemaFor(instance).mergeFrom(
- // instance, input, offset, offset + length,
- // new ArrayDecoders.Registers(extensionRegistry));
- // } catch (InvalidProtocolBufferException e) {
- // throw e;
- // } catch (IndexOutOfBoundsException e) {
- // throw InvalidProtocolBufferException.truncatedMessage();
- // } catch (IOException e) {
- // throw new RuntimeException("Reading from byte array should not throw IOException.", e);
- // }
- // return (BuilderType) this;
- // END EXPERIMENTAL
+ copyOnWrite();
+ try {
+ Protobuf.getInstance().schemaFor(instance).mergeFrom(
+ instance, input, offset, offset + length,
+ new ArrayDecoders.Registers(extensionRegistry));
+ } catch (InvalidProtocolBufferException e) {
+ throw e;
+ } catch (IndexOutOfBoundsException e) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ } catch (IOException e) {
+ throw new RuntimeException("Reading from byte array should not throw IOException.", e);
+ }
+ return (BuilderType) this;
}
@Override
public BuilderType mergeFrom(
byte[] input, int offset, int length)
throws InvalidProtocolBufferException {
- // BEGIN REGULAR
- return super.mergeFrom(input, offset, length);
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry());
- // END EXPERIMENTAL
+ return mergeFrom(input, offset, length, ExtensionRegistryLite.getEmptyRegistry());
}
@Override
@@ -493,15 +450,10 @@ public abstract class GeneratedMessageLite<
throws IOException {
copyOnWrite();
try {
- // BEGIN REGULAR
- instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
- // // fast path.
- // Protobuf.getInstance().schemaFor(instance).mergeFrom(
- // instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
- // END EXPERIMENTAL
+ // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
+ // fast path.
+ Protobuf.getInstance().schemaFor(instance).mergeFrom(
+ instance, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
} catch (RuntimeException e) {
if (e.getCause() instanceof IOException) {
throw (IOException) e.getCause();
@@ -553,14 +505,6 @@ public abstract class GeneratedMessageLite<
extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
- // BEGIN REGULAR
- @Override
- final void visit(Visitor visitor, MessageType other) {
- super.visit(visitor, other);
- extensions = visitor.visitExtensions(extensions, other.extensions);
- }
- // END REGULAR
-
/**
* Parse an unknown field or an extension. For use by generated code only.
*
@@ -898,14 +842,6 @@ public abstract class GeneratedMessageLite<
return extensions.isInitialized();
}
- @Override
- protected final void makeImmutable() {
- super.makeImmutable();
- // BEGIN REGULAR
- extensions.makeImmutable();
- // END REGULAR
- }
-
/**
* 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
@@ -1479,13 +1415,7 @@ public abstract class GeneratedMessageLite<
if (memoizedIsInitialized == 0) {
return false;
}
- // BEGIN EXPERIMENTAL
- // boolean isInitialized = Protobuf.getInstance().schemaFor(message).isInitialized(message);
- // END EXPERIMENTAL
- // BEGIN REGULAR
- boolean isInitialized =
- message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.FALSE) != null;
- // END REGULAR
+ boolean isInitialized = Protobuf.getInstance().schemaFor(message).isInitialized(message);
if (shouldMemoize) {
message.dynamicMethod(
MethodToInvoke.SET_MEMOIZED_IS_INITIALIZED, isInitialized ? message : null);
@@ -1593,23 +1523,16 @@ public abstract class GeneratedMessageLite<
@SuppressWarnings("unchecked") // Guaranteed by protoc
T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
try {
- // BEGIN REGULAR
- result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
- // // fast path.
- // Protobuf.getInstance().schemaFor(result).mergeFrom(
- // result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
- // END EXPERIMENTAL
+ // TODO(yilunchong): Try to make input with type CodedInpuStream.ArrayDecoder use
+ // fast path.
+ Protobuf.getInstance().schemaFor(result).mergeFrom(
+ result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
result.makeImmutable();
- // BEGIN EXPERIMENTAL
- // } catch (IOException e) {
- // if (e.getCause() instanceof InvalidProtocolBufferException) {
- // throw (InvalidProtocolBufferException) e.getCause();
- // }
- // throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
- // END EXPERIMENTAL
+ } catch (IOException e) {
+ if (e.getCause() instanceof InvalidProtocolBufferException) {
+ throw (InvalidProtocolBufferException) e.getCause();
+ }
+ throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
} catch (RuntimeException e) {
if (e.getCause() instanceof InvalidProtocolBufferException) {
throw (InvalidProtocolBufferException) e.getCause();
@@ -1623,42 +1546,25 @@ public abstract class GeneratedMessageLite<
static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
T instance, byte[] input, int offset, int length, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- // BEGIN REGULAR
- T message;
+ @SuppressWarnings("unchecked") // Guaranteed by protoc
+ T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
try {
- CodedInputStream cis = CodedInputStream.newInstance(input, offset, length);
- message = parsePartialFrom(instance, cis, extensionRegistry);
- try {
- cis.checkLastTagWas(0);
- } catch (InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(message);
+ Protobuf.getInstance().schemaFor(result).mergeFrom(
+ result, input, offset, offset + length,
+ new ArrayDecoders.Registers(extensionRegistry));
+ result.makeImmutable();
+ if (result.memoizedHashCode != 0) {
+ throw new RuntimeException();
}
- return message;
- } catch (InvalidProtocolBufferException e) {
- throw e;
+ } catch (IOException e) {
+ if (e.getCause() instanceof InvalidProtocolBufferException) {
+ throw (InvalidProtocolBufferException) e.getCause();
+ }
+ throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
+ } catch (IndexOutOfBoundsException e) {
+ throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
}
- // END REGULAR
- // BEGIN EXPERIMENTAL
- // @SuppressWarnings("unchecked") // Guaranteed by protoc
- // T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
- // try {
- // Protobuf.getInstance().schemaFor(result).mergeFrom(
- // result, input, offset, offset + length,
- // new ArrayDecoders.Registers(extensionRegistry));
- // result.makeImmutable();
- // if (result.memoizedHashCode != 0) {
- // throw new RuntimeException();
- // }
- // } catch (IOException e) {
- // if (e.getCause() instanceof InvalidProtocolBufferException) {
- // throw (InvalidProtocolBufferException) e.getCause();
- // }
- // throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
- // } catch (IndexOutOfBoundsException e) {
- // throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
- // }
- // return result;
- // END EXPERIMENTAL
+ return result;
}
protected static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
@@ -1825,701 +1731,4 @@ public abstract class GeneratedMessageLite<
}
return message;
}
-
- // BEGIN REGULAR
- /**
- * 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 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);
-
- <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 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 <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. */
- 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.
-
- 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 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 <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 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 <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;
- }
- }
- // END REGULAR
}
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
index e9eb34f2f..0ed724384 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -459,6 +459,29 @@ public abstract class GeneratedMessageV3 extends AbstractMessage
/**
+ * This class is used to make a generated protected method inaccessible from user's code (e.g.,
+ * the {@link #newInstance} method below). When this class is used as a parameter's type in a
+ * generated protected method, the method is visible to user's code in the same package, but
+ * since the constructor of this class is private to protobuf runtime, user's code can't obtain
+ * an instance of this class and as such can't actually make a method call on the protected
+ * method.
+ */
+ protected static final class UnusedPrivateParameter {
+ static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter();
+
+ private UnusedPrivateParameter() {
+ }
+ }
+
+ /**
+ * Creates a new instance of this message type. Overridden in the generated code.
+ */
+ @SuppressWarnings({"unused"})
+ protected Object newInstance(UnusedPrivateParameter unused) {
+ throw new UnsupportedOperationException("This method must be overridden by the subclass.");
+ }
+
+ /**
* Used by parsing constructors in generated classes.
*/
protected void makeExtensionsImmutable() {
diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index 713ccb583..15deb37c4 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -540,6 +540,24 @@ public final class Internal {
}
return valueConverter.doForward(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 getKey().equals(other.getKey()) && getValue().equals(getValue());
+ }
+
+ @Override
+ public int hashCode() {
+ return realEntry.hashCode();
+ }
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/JavaType.java b/java/core/src/main/java/com/google/protobuf/JavaType.java
new file mode 100755
index 000000000..770aa9ef1
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/JavaType.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;
+
+/** Enum that identifies the Java types required to store protobuf fields. */
+@ExperimentalApi
+public enum JavaType {
+ VOID(Void.class, Void.class, null),
+ INT(int.class, Integer.class, 0),
+ LONG(long.class, Long.class, 0L),
+ FLOAT(float.class, Float.class, 0F),
+ DOUBLE(double.class, Double.class, 0D),
+ BOOLEAN(boolean.class, Boolean.class, false),
+ STRING(String.class, String.class, ""),
+ BYTE_STRING(ByteString.class, ByteString.class, ByteString.EMPTY),
+ ENUM(int.class, Integer.class, null),
+ MESSAGE(Object.class, Object.class, null);
+
+ private final Class<?> type;
+ private final Class<?> boxedType;
+ private final Object defaultDefault;
+
+ JavaType(Class<?> type, Class<?> boxedType, Object defaultDefault) {
+ this.type = type;
+ this.boxedType = boxedType;
+ this.defaultDefault = defaultDefault;
+ }
+
+ /** The default default value for fields of this type, if it's a primitive type. */
+ public Object getDefaultDefault() {
+ return defaultDefault;
+ }
+
+ /** Gets the required type for a field that would hold a value of this type. */
+ public Class<?> getType() {
+ return type;
+ }
+
+ /** @return the boxedType */
+ public Class<?> getBoxedType() {
+ return boxedType;
+ }
+
+ /** Indicates whether or not this {@link JavaType} can be applied to a field of the given type. */
+ public boolean isValidType(Class<?> t) {
+ return type.isAssignableFrom(t);
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
index 5651e131b..d6b594d38 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -388,6 +388,18 @@ public class LazyFieldLite {
}
}
+ /** Writes this lazy field into a {@link Writer}. */
+ void writeTo(Writer writer, int fieldNumber) throws IOException {
+ if (memoizedBytes != null) {
+ writer.writeBytes(fieldNumber, memoizedBytes);
+ } else if (delayedBytes != null) {
+ writer.writeBytes(fieldNumber, delayedBytes);
+ } else if (value != null) {
+ writer.writeMessage(fieldNumber, value);
+ } else {
+ writer.writeBytes(fieldNumber, ByteString.EMPTY);
+ }
+ }
/** Might lazily parse the bytes that were previously passed in. Is thread-safe. */
protected void ensureInitialized(MessageLite defaultInstance) {
diff --git a/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java
new file mode 100755
index 000000000..ebc8561a7
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ListFieldSchema.java
@@ -0,0 +1,190 @@
+// 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.Collections;
+import java.util.List;
+
+/**
+ * Utility class that aids in properly manipulating list fields for either the lite or full runtime.
+ */
+abstract class ListFieldSchema {
+ // Disallow construction.
+ private ListFieldSchema() {}
+
+ private static final ListFieldSchema FULL_INSTANCE = new ListFieldSchemaFull();
+ private static final ListFieldSchema LITE_INSTANCE = new ListFieldSchemaLite();
+
+ abstract <L> List<L> mutableListAt(Object msg, long offset);
+
+ abstract void makeImmutableListAt(Object msg, long offset);
+
+ abstract <L> void mergeListsAt(Object msg, Object otherMsg, long offset);
+
+ static ListFieldSchema full() {
+ return FULL_INSTANCE;
+ }
+
+ static ListFieldSchema lite() {
+ return LITE_INSTANCE;
+ }
+
+ /** Implementation for the full runtime. */
+ private static final class ListFieldSchemaFull extends ListFieldSchema {
+
+ private static final Class<?> UNMODIFIABLE_LIST_CLASS =
+ Collections.unmodifiableList(Collections.emptyList()).getClass();
+
+ @Override
+ <L> List<L> mutableListAt(Object message, long offset) {
+ return mutableListAt(message, offset, AbstractProtobufList.DEFAULT_CAPACITY);
+ }
+
+ @Override
+ void makeImmutableListAt(Object message, long offset) {
+ List<?> list = (List<?>) UnsafeUtil.getObject(message, offset);
+ Object immutable = null;
+ if (list instanceof LazyStringList) {
+ immutable = ((LazyStringList) list).getUnmodifiableView();
+ } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) {
+ // already immutable
+ return;
+ } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) {
+ if (((ProtobufList<?>) list).isModifiable()) {
+ ((ProtobufList<?>) list).makeImmutable();
+ }
+ return;
+ } else {
+ immutable = Collections.unmodifiableList((List<?>) list);
+ }
+ UnsafeUtil.putObject(message, offset, immutable);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <L> List<L> mutableListAt(Object message, long offset, int additionalCapacity) {
+ List<L> list = getList(message, offset);
+ if (list.isEmpty()) {
+ if (list instanceof LazyStringList) {
+ list = (List<L>) new LazyStringArrayList(additionalCapacity);
+ } else if (list instanceof PrimitiveNonBoxingCollection && list instanceof ProtobufList) {
+ list = ((ProtobufList<L>) list).mutableCopyWithCapacity(additionalCapacity);
+ } else {
+ list = new ArrayList<L>(additionalCapacity);
+ }
+ UnsafeUtil.putObject(message, offset, list);
+ } else if (UNMODIFIABLE_LIST_CLASS.isAssignableFrom(list.getClass())) {
+ ArrayList<L> newList = new ArrayList<L>(list.size() + additionalCapacity);
+ newList.addAll(list);
+ list = newList;
+ UnsafeUtil.putObject(message, offset, list);
+ } else if (list instanceof UnmodifiableLazyStringList) {
+ LazyStringArrayList newList = new LazyStringArrayList(list.size() + additionalCapacity);
+ newList.addAll((UnmodifiableLazyStringList) list);
+ list = (List<L>) newList;
+ UnsafeUtil.putObject(message, offset, list);
+ } else if (list instanceof PrimitiveNonBoxingCollection
+ && list instanceof ProtobufList
+ && !((ProtobufList<L>) list).isModifiable()) {
+ list = ((ProtobufList<L>) list).mutableCopyWithCapacity(list.size() + additionalCapacity);
+ UnsafeUtil.putObject(message, offset, list);
+ }
+ return list;
+ }
+
+ @Override
+ <E> void mergeListsAt(Object msg, Object otherMsg, long offset) {
+ List<E> other = getList(otherMsg, offset);
+ List<E> mine = mutableListAt(msg, offset, other.size());
+
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ mine.addAll(other);
+ }
+
+ List<E> merged = size > 0 ? mine : other;
+ UnsafeUtil.putObject(msg, offset, merged);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <E> List<E> getList(Object message, long offset) {
+ return (List<E>) UnsafeUtil.getObject(message, offset);
+ }
+ }
+
+ /** Implementation for the lite runtime. */
+ private static final class ListFieldSchemaLite extends ListFieldSchema {
+
+ @Override
+ <L> List<L> mutableListAt(Object message, long offset) {
+ ProtobufList<L> list = getProtobufList(message, offset);
+ if (!list.isModifiable()) {
+ int size = list.size();
+ list =
+ list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ UnsafeUtil.putObject(message, offset, list);
+ }
+ return list;
+ }
+
+ @Override
+ void makeImmutableListAt(Object message, long offset) {
+ ProtobufList<?> list = getProtobufList(message, offset);
+ list.makeImmutable();
+ }
+
+ @Override
+ <E> void mergeListsAt(Object msg, Object otherMsg, long offset) {
+ ProtobufList<E> mine = getProtobufList(msg, offset);
+ ProtobufList<E> other = getProtobufList(otherMsg, offset);
+
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ ProtobufList<E> merged = size > 0 ? mine : other;
+ UnsafeUtil.putObject(msg, offset, merged);
+ }
+
+ @SuppressWarnings("unchecked")
+ static <E> ProtobufList<E> getProtobufList(Object message, long offset) {
+ return (ProtobufList<E>) UnsafeUtil.getObject(message, offset);
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java
new file mode 100755
index 000000000..84ca9ae0f
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java
@@ -0,0 +1,172 @@
+// 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;
+
+/**
+ * Dynamically generates a manifest-based (i.e. table-based) schema for a given protobuf message.
+ */
+@ExperimentalApi
+final class ManifestSchemaFactory implements SchemaFactory {
+
+ private final MessageInfoFactory messageInfoFactory;
+
+ public ManifestSchemaFactory() {
+ this(getDefaultMessageInfoFactory());
+ }
+
+ private ManifestSchemaFactory(MessageInfoFactory messageInfoFactory) {
+ this.messageInfoFactory = checkNotNull(messageInfoFactory, "messageInfoFactory");
+ }
+
+ @Override
+ public <T> Schema<T> createSchema(Class<T> messageType) {
+ SchemaUtil.requireGeneratedMessage(messageType);
+
+ MessageInfo messageInfo = messageInfoFactory.messageInfoFor(messageType);
+
+ // MessageSet has a special schema.
+ if (messageInfo.isMessageSetWireFormat()) {
+ if (GeneratedMessageLite.class.isAssignableFrom(messageType)) {
+ return MessageSetSchema.newSchema(
+ SchemaUtil.unknownFieldSetLiteSchema(),
+ ExtensionSchemas.lite(),
+ messageInfo.getDefaultInstance());
+ }
+ return MessageSetSchema.newSchema(
+ SchemaUtil.proto2UnknownFieldSetSchema(),
+ ExtensionSchemas.full(),
+ messageInfo.getDefaultInstance());
+ }
+
+ return newSchema(messageType, messageInfo);
+ }
+
+ private static <T> Schema<T> newSchema(Class<T> messageType, MessageInfo messageInfo) {
+ if (GeneratedMessageLite.class.isAssignableFrom(messageType)) {
+ return isProto2(messageInfo)
+ ? MessageSchema.newSchema(
+ messageType,
+ messageInfo,
+ NewInstanceSchemas.lite(),
+ ListFieldSchema.lite(),
+ SchemaUtil.unknownFieldSetLiteSchema(),
+ ExtensionSchemas.lite(),
+ MapFieldSchemas.lite())
+ : MessageSchema.newSchema(
+ messageType,
+ messageInfo,
+ NewInstanceSchemas.lite(),
+ ListFieldSchema.lite(),
+ SchemaUtil.unknownFieldSetLiteSchema(),
+ /* extensionSchema= */ null,
+ MapFieldSchemas.lite());
+ }
+ return isProto2(messageInfo)
+ ? MessageSchema.newSchema(
+ messageType,
+ messageInfo,
+ NewInstanceSchemas.full(),
+ ListFieldSchema.full(),
+ SchemaUtil.proto2UnknownFieldSetSchema(),
+ ExtensionSchemas.full(),
+ MapFieldSchemas.full())
+ : MessageSchema.newSchema(
+ messageType,
+ messageInfo,
+ NewInstanceSchemas.full(),
+ ListFieldSchema.full(),
+ SchemaUtil.proto3UnknownFieldSetSchema(),
+ /* extensionSchema= */ null,
+ MapFieldSchemas.full());
+ }
+
+ private static boolean isProto2(MessageInfo messageInfo) {
+ return messageInfo.getSyntax() == ProtoSyntax.PROTO2;
+ }
+
+ private static MessageInfoFactory getDefaultMessageInfoFactory() {
+ return new CompositeMessageInfoFactory(
+ GeneratedMessageInfoFactory.getInstance(), getDescriptorMessageInfoFactory());
+ }
+
+ private static class CompositeMessageInfoFactory implements MessageInfoFactory {
+ private MessageInfoFactory[] factories;
+
+ CompositeMessageInfoFactory(MessageInfoFactory... factories) {
+ this.factories = factories;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ for (MessageInfoFactory factory : factories) {
+ if (factory.isSupported(clazz)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ for (MessageInfoFactory factory : factories) {
+ if (factory.isSupported(clazz)) {
+ return factory.messageInfoFor(clazz);
+ }
+ }
+ throw new UnsupportedOperationException(
+ "No factory is available for message type: " + clazz.getName());
+ }
+ }
+
+ private static final MessageInfoFactory EMPTY_FACTORY =
+ new MessageInfoFactory() {
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ return false;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ throw new IllegalStateException("This should never be called.");
+ }
+ };
+
+ private static MessageInfoFactory getDescriptorMessageInfoFactory() {
+ try {
+ Class<?> clazz = Class.forName("com.google.protobuf.DescriptorMessageInfoFactory");
+ return (MessageInfoFactory) clazz.getDeclaredMethod("getInstance").invoke(null);
+ } catch (Exception e) {
+ return EMPTY_FACTORY;
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchema.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchema.java
new file mode 100755
index 000000000..195126e51
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchema.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;
+
+import java.util.Map;
+
+interface MapFieldSchema {
+ /** Returns the map data for mutation. */
+ Map<?, ?> forMutableMapData(Object mapField);
+
+ /** Returns the map data for read. */
+ Map<?, ?> forMapData(Object mapField);
+
+ /** Whether toImmutable() has been called on this map field. */
+ boolean isImmutable(Object mapField);
+
+ /**
+ * Returns an immutable instance of the map field. It may make the parameter immutable and return
+ * the parameter, or create an immutable copy. The status of the parameter after the call is
+ * undefined.
+ */
+ Object toImmutable(Object mapField);
+
+ /** Returns a new instance of the map field given a map default entry. */
+ Object newMapField(Object mapDefaultEntry);
+
+ /** Returns the metadata from a default entry. */
+ MapEntryLite.Metadata<?, ?> forMapMetadata(Object mapDefaultEntry);
+
+ /** Merges {@code srcMapField} into {@code destMapField}, and returns the merged instance. */
+ Object mergeFrom(Object destMapField, Object srcMapField);
+
+ /** Compute the serialized size for the map with a given field number. */
+ int getSerializedSize(int fieldNumber, Object mapField, Object mapDefaultEntry);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java
new file mode 100755
index 000000000..1efaab3bc
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java
@@ -0,0 +1,112 @@
+// 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.MapEntryLite.Metadata;
+import java.util.Map;
+
+class MapFieldSchemaFull implements MapFieldSchema {
+ @Override
+ public Map<?, ?> forMutableMapData(Object mapField) {
+ return ((MapField<?, ?>) mapField).getMutableMap();
+ }
+
+ @Override
+ public Map<?, ?> forMapData(Object mapField) {
+ return ((MapField<?, ?>) mapField).getMap();
+ }
+
+ @Override
+ public boolean isImmutable(Object mapField) {
+ return !((MapField<?, ?>) mapField).isMutable();
+ }
+
+ @Override
+ public Object toImmutable(Object mapField) {
+ ((MapField<?, ?>) mapField).makeImmutable();
+ return mapField;
+ }
+
+ @Override
+ public Object newMapField(Object mapDefaultEntry) {
+ return MapField.newMapField((MapEntry<?, ?>) mapDefaultEntry);
+ }
+
+ @Override
+ public Metadata<?, ?> forMapMetadata(Object mapDefaultEntry) {
+ return ((MapEntry<?, ?>) mapDefaultEntry).getMetadata();
+ }
+
+ @Override
+ public Object mergeFrom(Object destMapField, Object srcMapField) {
+ return mergeFromFull(destMapField, srcMapField);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <K, V> Object mergeFromFull(Object destMapField, Object srcMapField) {
+ MapField<K, V> mine = (MapField<K, V>) destMapField;
+ MapField<K, V> other = (MapField<K, V>) srcMapField;
+ if (!mine.isMutable()) {
+ mine.copy();
+ }
+ mine.mergeFrom(other);
+ return mine;
+ }
+
+ @Override
+ public int getSerializedSize(int number, Object mapField, Object mapDefaultEntry) {
+ return getSerializedSizeFull(number, mapField, mapDefaultEntry);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <K, V> int getSerializedSizeFull(
+ int number, Object mapField, Object defaultEntryObject) {
+ // Full runtime allocates map fields lazily.
+ if (mapField == null) {
+ return 0;
+ }
+
+ Map<K, V> map = ((MapField<K, V>) mapField).getMap();
+ MapEntry<K, V> defaultEntry = (MapEntry<K, V>) defaultEntryObject;
+ if (map.isEmpty()) {
+ return 0;
+ }
+ int size = 0;
+ for (Map.Entry<K, V> entry : map.entrySet()) {
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(
+ MapEntryLite.computeSerializedSize(
+ defaultEntry.getMetadata(), entry.getKey(), entry.getValue()));
+ }
+ return size;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java
new file mode 100755
index 000000000..8a8c78de8
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java
@@ -0,0 +1,107 @@
+// 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.MapEntryLite.Metadata;
+import java.util.Map;
+
+class MapFieldSchemaLite implements MapFieldSchema {
+
+ @Override
+ public Map<?, ?> forMutableMapData(Object mapField) {
+ return (MapFieldLite<?, ?>) mapField;
+ }
+
+ @Override
+ public Metadata<?, ?> forMapMetadata(Object mapDefaultEntry) {
+ return ((MapEntryLite<?, ?>) mapDefaultEntry).getMetadata();
+ }
+
+ @Override
+ public Map<?, ?> forMapData(Object mapField) {
+ return (MapFieldLite<?, ?>) mapField;
+ }
+
+ @Override
+ public boolean isImmutable(Object mapField) {
+ return !((MapFieldLite<?, ?>) mapField).isMutable();
+ }
+
+ @Override
+ public Object toImmutable(Object mapField) {
+ ((MapFieldLite<?, ?>) mapField).makeImmutable();
+ return mapField;
+ }
+
+ @Override
+ public Object newMapField(Object unused) {
+ return MapFieldLite.emptyMapField().mutableCopy();
+ }
+
+ @Override
+ public Object mergeFrom(Object destMapField, Object srcMapField) {
+ return mergeFromLite(destMapField, srcMapField);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <K, V> MapFieldLite<K, V> mergeFromLite(Object destMapField, Object srcMapField) {
+ MapFieldLite<K, V> mine = (MapFieldLite<K, V>) destMapField;
+ MapFieldLite<K, V> other = (MapFieldLite<K, V>) srcMapField;
+ if (!other.isEmpty()) {
+ if (!mine.isMutable()) {
+ mine = mine.mutableCopy();
+ }
+ mine.mergeFrom(other);
+ }
+ return mine;
+ }
+
+ @Override
+ public int getSerializedSize(int fieldNumber, Object mapField, Object mapDefaultEntry) {
+ return getSerializedSizeLite(fieldNumber, mapField, mapDefaultEntry);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <K, V> int getSerializedSizeLite(
+ int fieldNumber, Object mapField, Object defaultEntry) {
+ MapFieldLite<K, V> mapFieldLite = (MapFieldLite<K, V>) mapField;
+ MapEntryLite<K, V> defaultEntryLite = (MapEntryLite<K, V>) defaultEntry;
+
+ if (mapFieldLite.isEmpty()) {
+ return 0;
+ }
+ int size = 0;
+ for (Map.Entry<K, V> entry : mapFieldLite.entrySet()) {
+ size += defaultEntryLite.computeMessageSize(fieldNumber, entry.getKey(), entry.getValue());
+ }
+ return size;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java
new file mode 100755
index 000000000..b398c6102
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java
@@ -0,0 +1,53 @@
+// 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;
+
+final class MapFieldSchemas {
+ private static final MapFieldSchema FULL_SCHEMA = loadSchemaForFullRuntime();
+ private static final MapFieldSchema LITE_SCHEMA = new MapFieldSchemaLite();
+
+ static MapFieldSchema full() {
+ return FULL_SCHEMA;
+ }
+
+ static MapFieldSchema lite() {
+ return LITE_SCHEMA;
+ }
+
+ private static MapFieldSchema loadSchemaForFullRuntime() {
+ try {
+ Class<?> clazz = Class.forName("com.google.protobuf.MapFieldSchemaFull");
+ return (MapFieldSchema) clazz.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageInfo.java b/java/core/src/main/java/com/google/protobuf/MessageInfo.java
new file mode 100755
index 000000000..69e318696
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MessageInfo.java
@@ -0,0 +1,43 @@
+// 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 MesageInfo object describes a proto message type. */
+interface MessageInfo {
+ /** Gets syntax for this type. */
+ ProtoSyntax getSyntax();
+
+ /** Whether this type is MessageSet. */
+ boolean isMessageSetWireFormat();
+
+ /** Gets the default instance of this type. */
+ MessageLite getDefaultInstance();
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java b/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java
new file mode 100755
index 000000000..005c26d05
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java
@@ -0,0 +1,41 @@
+// 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 factory that creates {@link MessageInfo} instances for message types. */
+@ExperimentalApi
+interface MessageInfoFactory {
+ /** Whether the message class is supported by this factory. */
+ boolean isSupported(Class<?> clazz);
+
+ /** Returns a information of the message class. */
+ MessageInfo messageInfoFor(Class<?> clazz);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
new file mode 100755
index 000000000..67584ed41
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MessageSchema.java
@@ -0,0 +1,5886 @@
+// 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.ArrayDecoders.decodeBoolList;
+import static com.google.protobuf.ArrayDecoders.decodeBytes;
+import static com.google.protobuf.ArrayDecoders.decodeBytesList;
+import static com.google.protobuf.ArrayDecoders.decodeDouble;
+import static com.google.protobuf.ArrayDecoders.decodeDoubleList;
+import static com.google.protobuf.ArrayDecoders.decodeExtensionOrUnknownField;
+import static com.google.protobuf.ArrayDecoders.decodeFixed32;
+import static com.google.protobuf.ArrayDecoders.decodeFixed32List;
+import static com.google.protobuf.ArrayDecoders.decodeFixed64;
+import static com.google.protobuf.ArrayDecoders.decodeFixed64List;
+import static com.google.protobuf.ArrayDecoders.decodeFloat;
+import static com.google.protobuf.ArrayDecoders.decodeFloatList;
+import static com.google.protobuf.ArrayDecoders.decodeGroupField;
+import static com.google.protobuf.ArrayDecoders.decodeGroupList;
+import static com.google.protobuf.ArrayDecoders.decodeMessageField;
+import static com.google.protobuf.ArrayDecoders.decodeMessageList;
+import static com.google.protobuf.ArrayDecoders.decodePackedBoolList;
+import static com.google.protobuf.ArrayDecoders.decodePackedDoubleList;
+import static com.google.protobuf.ArrayDecoders.decodePackedFixed32List;
+import static com.google.protobuf.ArrayDecoders.decodePackedFixed64List;
+import static com.google.protobuf.ArrayDecoders.decodePackedFloatList;
+import static com.google.protobuf.ArrayDecoders.decodePackedSInt32List;
+import static com.google.protobuf.ArrayDecoders.decodePackedSInt64List;
+import static com.google.protobuf.ArrayDecoders.decodePackedVarint32List;
+import static com.google.protobuf.ArrayDecoders.decodePackedVarint64List;
+import static com.google.protobuf.ArrayDecoders.decodeSInt32List;
+import static com.google.protobuf.ArrayDecoders.decodeSInt64List;
+import static com.google.protobuf.ArrayDecoders.decodeString;
+import static com.google.protobuf.ArrayDecoders.decodeStringList;
+import static com.google.protobuf.ArrayDecoders.decodeStringListRequireUtf8;
+import static com.google.protobuf.ArrayDecoders.decodeStringRequireUtf8;
+import static com.google.protobuf.ArrayDecoders.decodeUnknownField;
+import static com.google.protobuf.ArrayDecoders.decodeVarint32;
+import static com.google.protobuf.ArrayDecoders.decodeVarint32List;
+import static com.google.protobuf.ArrayDecoders.decodeVarint64;
+import static com.google.protobuf.ArrayDecoders.decodeVarint64List;
+import static com.google.protobuf.ArrayDecoders.skipField;
+
+import com.google.protobuf.ArrayDecoders.Registers;
+import com.google.protobuf.ByteString.CodedBuilder;
+import com.google.protobuf.FieldSet.FieldDescriptorLite;
+import com.google.protobuf.Internal.EnumVerifier;
+import com.google.protobuf.Internal.ProtobufList;
+import com.google.protobuf.MapEntryLite.Metadata;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/** Schema used for standard messages. */
+final class MessageSchema<T> implements Schema<T> {
+ private static final int INTS_PER_FIELD = 3;
+ private static final int OFFSET_BITS = 20;
+ private static final int OFFSET_MASK = 0XFFFFF;
+ private static final int FIELD_TYPE_MASK = 0x0FF00000;
+ private static final int REQUIRED_MASK = 0x10000000;
+ private static final int ENFORCE_UTF8_MASK = 0x20000000;
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
+
+ /** An offset applied to the field type ID for scalar fields that are a member of a oneof. */
+ static final int ONEOF_TYPE_OFFSET = 51 /* FieldType.MAP + 1 */;
+
+ /**
+ * Keep a direct reference to the unsafe object so we don't need to go through the UnsafeUtil
+ * wrapper for every call.
+ */
+ private static final sun.misc.Unsafe UNSAFE = UnsafeUtil.getUnsafe();
+
+ /**
+ * Holds all information for accessing the message fields. The layout is as follows (field
+ * positions are relative to the offset of the start of the field in the buffer):
+ *
+ * <p>
+ *
+ * <pre>
+ * [ 0 - 3] unused
+ * [ 4 - 31] field number
+ * [32 - 33] unused
+ * [34 - 34] whether UTF-8 enforcement should be applied to a string field.
+ * [35 - 35] whether the field is required
+ * [36 - 43] field type / for oneof: field type + {@link #ONEOF_TYPE_OFFSET}
+ * [44 - 63] field offset / oneof value field offset
+ * [64 - 69] unused
+ * [70 - 75] field presence mask shift (unused for oneof/repeated fields)
+ * [76 - 95] presence field offset / oneof case field offset / cached size field offset
+ * </pre>
+ */
+ private final int[] buffer;
+
+ /**
+ * Holds object references for fields. For each field entry in {@code buffer}, there are two
+ * corresponding entries in this array. The content is different from different field types:
+ *
+ * <pre>
+ * Map fields:
+ * objects[pos] = map default entry instance
+ * objects[pos + 1] = EnumVerifier if map value is enum, or message class reference if map
+ * value is message.
+ * Message fields:
+ * objects[pos] = null or cached message schema
+ * objects[pos + 1] = message class reference
+ * Enum fields:
+ * objects[pos] = null
+ * objects[pos + 1] = EnumVerifier
+ * </pre>
+ */
+ private final Object[] objects;
+
+ private final int minFieldNumber;
+ private final int maxFieldNumber;
+
+ private final MessageLite defaultInstance;
+ private final boolean hasExtensions;
+ private final boolean lite;
+ private final boolean proto3;
+ // TODO(xiaofeng): Make both full-runtime and lite-runtime support cached field size.
+ private final boolean useCachedSizeField;
+
+ /** Represents [checkInitialized positions, map field positions, repeated field offsets]. */
+ private final int[] intArray;
+
+ /**
+ * Values at indices 0 -> checkInitializedCount in intArray are positions to check for
+ * initialization.
+ */
+ private final int checkInitializedCount;
+
+ /**
+ * Values at indices checkInitializedCount -> repeatedFieldOffsetStart are map positions.
+ * Everything after that are repeated field offsets.
+ */
+ private final int repeatedFieldOffsetStart;
+
+ private final NewInstanceSchema newInstanceSchema;
+ private final ListFieldSchema listFieldSchema;
+ private final UnknownFieldSchema<?, ?> unknownFieldSchema;
+ private final ExtensionSchema<?> extensionSchema;
+ private final MapFieldSchema mapFieldSchema;
+
+ private MessageSchema(
+ int[] buffer,
+ Object[] objects,
+ int minFieldNumber,
+ int maxFieldNumber,
+ MessageLite defaultInstance,
+ boolean proto3,
+ boolean useCachedSizeField,
+ int[] intArray,
+ int checkInitialized,
+ int mapFieldPositions,
+ NewInstanceSchema newInstanceSchema,
+ ListFieldSchema listFieldSchema,
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MapFieldSchema mapFieldSchema) {
+ this.buffer = buffer;
+ this.objects = objects;
+ this.minFieldNumber = minFieldNumber;
+ this.maxFieldNumber = maxFieldNumber;
+
+ this.lite = defaultInstance instanceof GeneratedMessageLite;
+ this.proto3 = proto3;
+ this.hasExtensions = extensionSchema != null && extensionSchema.hasExtensions(defaultInstance);
+ this.useCachedSizeField = useCachedSizeField;
+
+ this.intArray = intArray;
+ this.checkInitializedCount = checkInitialized;
+ this.repeatedFieldOffsetStart = mapFieldPositions;
+
+ this.newInstanceSchema = newInstanceSchema;
+ this.listFieldSchema = listFieldSchema;
+ this.unknownFieldSchema = unknownFieldSchema;
+ this.extensionSchema = extensionSchema;
+ this.defaultInstance = defaultInstance;
+ this.mapFieldSchema = mapFieldSchema;
+ }
+
+ static <T> MessageSchema<T> newSchema(
+ Class<T> messageClass,
+ MessageInfo messageInfo,
+ NewInstanceSchema newInstanceSchema,
+ ListFieldSchema listFieldSchema,
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MapFieldSchema mapFieldSchema) {
+ if (messageInfo instanceof RawMessageInfo) {
+ return newSchemaForRawMessageInfo(
+ (RawMessageInfo) messageInfo,
+ newInstanceSchema,
+ listFieldSchema,
+ unknownFieldSchema,
+ extensionSchema,
+ mapFieldSchema);
+
+ } else {
+ return newSchemaForMessageInfo(
+ (StructuralMessageInfo) messageInfo,
+ newInstanceSchema,
+ listFieldSchema,
+ unknownFieldSchema,
+ extensionSchema,
+ mapFieldSchema);
+ }
+ }
+
+ static <T> MessageSchema<T> newSchemaForRawMessageInfo(
+ RawMessageInfo messageInfo,
+ NewInstanceSchema newInstanceSchema,
+ ListFieldSchema listFieldSchema,
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MapFieldSchema mapFieldSchema) {
+ final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3;
+
+ String info = messageInfo.getStringInfo();
+ final int length = info.length();
+ int i = 0;
+
+ int next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ final int flags = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ final int fieldCount = next;
+
+ final int oneofCount;
+ final int hasBitsCount;
+ final int minFieldNumber;
+ final int maxFieldNumber;
+ final int numEntries;
+ final int mapFieldCount;
+ final int repeatedFieldCount;
+ final int checkInitialized;
+ final int[] intArray;
+ int objectsPosition;
+ if (fieldCount == 0) {
+ oneofCount = 0;
+ hasBitsCount = 0;
+ minFieldNumber = 0;
+ maxFieldNumber = 0;
+ numEntries = 0;
+ mapFieldCount = 0;
+ repeatedFieldCount = 0;
+ checkInitialized = 0;
+ intArray = EMPTY_INT_ARRAY;
+ objectsPosition = 0;
+ } else {
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ oneofCount = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ hasBitsCount = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ minFieldNumber = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ maxFieldNumber = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ numEntries = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ mapFieldCount = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ repeatedFieldCount = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ checkInitialized = next;
+ intArray = new int[checkInitialized + mapFieldCount + repeatedFieldCount];
+ // Field objects are after a list of (oneof, oneofCase) pairs + a list of hasbits fields.
+ objectsPosition = oneofCount * 2 + hasBitsCount;
+ }
+
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ final Object[] messageInfoObjects = messageInfo.getObjects();
+ int checkInitializedPosition = 0;
+ final Class<?> messageClass = messageInfo.getDefaultInstance().getClass();
+ int[] buffer = new int[numEntries * INTS_PER_FIELD];
+ Object[] objects = new Object[numEntries * 2];
+
+ int mapFieldIndex = checkInitialized;
+ int repeatedFieldIndex = checkInitialized + mapFieldCount;
+
+ int bufferIndex = 0;
+ while (i < length) {
+ final int fieldNumber;
+ final int fieldTypeWithExtraBits;
+ final int fieldType;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ fieldNumber = next;
+
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ fieldTypeWithExtraBits = next;
+ fieldType = fieldTypeWithExtraBits & 0xFF;
+
+ if ((fieldTypeWithExtraBits & 0x400) != 0) {
+ intArray[checkInitializedPosition++] = bufferIndex;
+ }
+
+ final int fieldOffset;
+ final int presenceMaskShift;
+ final int presenceFieldOffset;
+
+ // Oneof
+ if (fieldType >= ONEOF_TYPE_OFFSET) {
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ int oneofIndex = next;
+
+ final int oneofFieldType = fieldType - ONEOF_TYPE_OFFSET;
+ if (oneofFieldType == 9 /* FieldType.MESSAGE */
+ || oneofFieldType == 17 /* FieldType.GROUP */) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
+ } else if (oneofFieldType == 12 /* FieldType.ENUM */) {
+ // proto2
+ if ((flags & 0x1) == 0x1) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
+ }
+ }
+
+ final java.lang.reflect.Field oneofField;
+ int index = oneofIndex * 2;
+ Object o = messageInfoObjects[index];
+ if (o instanceof java.lang.reflect.Field) {
+ oneofField = (java.lang.reflect.Field) o;
+ } else {
+ oneofField = reflectField(messageClass, (String) o);
+ // Memoize java.lang.reflect.Field instances for oneof/hasbits fields, since they're
+ // potentially used for many Protobuf fields. Since there's a 1-1 mapping from the
+ // Protobuf field to the Java Field for non-oneofs, there's no benefit for memoizing
+ // those.
+ messageInfoObjects[index] = oneofField;
+ }
+
+ fieldOffset = (int) unsafe.objectFieldOffset(oneofField);
+
+ final java.lang.reflect.Field oneofCaseField;
+ index++;
+ o = messageInfoObjects[index];
+ if (o instanceof java.lang.reflect.Field) {
+ oneofCaseField = (java.lang.reflect.Field) o;
+ } else {
+ oneofCaseField = reflectField(messageClass, (String) o);
+ messageInfoObjects[index] = oneofCaseField;
+ }
+
+ presenceFieldOffset = (int) unsafe.objectFieldOffset(oneofCaseField);
+ presenceMaskShift = 0;
+ } else {
+ Field field = reflectField(messageClass, (String) messageInfoObjects[objectsPosition++]);
+ if (fieldType == 9 /* FieldType.MESSAGE */ || fieldType == 17 /* FieldType.GROUP */) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = field.getType();
+ } else if (fieldType == 27 /* FieldType.MESSAGE_LIST */
+ || fieldType == 49 /* FieldType.GROUP_LIST */) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
+ } else if (fieldType == 12 /* FieldType.ENUM */
+ || fieldType == 30 /* FieldType.ENUM_LIST */
+ || fieldType == 44 /* FieldType.ENUM_LIST_PACKED */) {
+ if ((flags & 0x1) == 0x1) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
+ }
+ } else if (fieldType == 50 /* FieldType.MAP */) {
+ intArray[mapFieldIndex++] = bufferIndex;
+ objects[bufferIndex / INTS_PER_FIELD * 2] = messageInfoObjects[objectsPosition++];
+ if ((fieldTypeWithExtraBits & 0x800) != 0) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageInfoObjects[objectsPosition++];
+ }
+ }
+
+ fieldOffset = (int) unsafe.objectFieldOffset(field);
+ if ((flags & 0x1) == 0x1 && fieldType <= 17 /* FieldType.GROUP */) {
+ next = info.charAt(i++);
+ if (next >= 0xD800) {
+ int result = next & 0x1FFF;
+ int shift = 13;
+ while ((next = info.charAt(i++)) >= 0xD800) {
+ result |= (next & 0x1FFF) << shift;
+ shift += 13;
+ }
+ next = result | (next << shift);
+ }
+ int hasBitsIndex = next;
+
+ final java.lang.reflect.Field hasBitsField;
+ int index = oneofCount * 2 + hasBitsIndex / 32;
+ Object o = messageInfoObjects[index];
+ if (o instanceof java.lang.reflect.Field) {
+ hasBitsField = (java.lang.reflect.Field) o;
+ } else {
+ hasBitsField = reflectField(messageClass, (String) o);
+ messageInfoObjects[index] = hasBitsField;
+ }
+
+ presenceFieldOffset = (int) unsafe.objectFieldOffset(hasBitsField);
+ presenceMaskShift = hasBitsIndex % 32;
+ } else {
+ presenceFieldOffset = 0;
+ presenceMaskShift = 0;
+ }
+
+ if (fieldType >= 18 && fieldType <= 49) {
+ // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
+ // 49 (GROUP_LIST).
+ intArray[repeatedFieldIndex++] = fieldOffset;
+ }
+ }
+
+ buffer[bufferIndex++] = fieldNumber;
+ buffer[bufferIndex++] =
+ ((fieldTypeWithExtraBits & 0x200) != 0 ? ENFORCE_UTF8_MASK : 0)
+ | ((fieldTypeWithExtraBits & 0x100) != 0 ? REQUIRED_MASK : 0)
+ | (fieldType << OFFSET_BITS)
+ | fieldOffset;
+ buffer[bufferIndex++] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset;
+ }
+
+ return new MessageSchema<T>(
+ buffer,
+ objects,
+ minFieldNumber,
+ maxFieldNumber,
+ messageInfo.getDefaultInstance(),
+ isProto3,
+ /* useCachedSizeField= */ false,
+ intArray,
+ checkInitialized,
+ checkInitialized + mapFieldCount,
+ newInstanceSchema,
+ listFieldSchema,
+ unknownFieldSchema,
+ extensionSchema,
+ mapFieldSchema);
+ }
+
+ private static java.lang.reflect.Field reflectField(Class<?> messageClass, String fieldName) {
+ try {
+ return messageClass.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ // Some Samsung devices lie about what fields are present via the getDeclaredField API so
+ // we do the for loop properly that they seem to have messed up...
+ java.lang.reflect.Field[] fields = messageClass.getDeclaredFields();
+ for (java.lang.reflect.Field field : fields) {
+ if (fieldName.equals(field.getName())) {
+ return field;
+ }
+ }
+
+ // If we make it here, the runtime still lies about what we know to be true at compile
+ // time. We throw to alert server monitoring for further remediation.
+ throw new RuntimeException(
+ "Field "
+ + fieldName
+ + " for "
+ + messageClass.getName()
+ + " not found. Known fields are "
+ + Arrays.toString(fields));
+ }
+ }
+
+ static <T> MessageSchema<T> newSchemaForMessageInfo(
+ StructuralMessageInfo messageInfo,
+ NewInstanceSchema newInstanceSchema,
+ ListFieldSchema listFieldSchema,
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MapFieldSchema mapFieldSchema) {
+ final boolean isProto3 = messageInfo.getSyntax() == ProtoSyntax.PROTO3;
+ FieldInfo[] fis = messageInfo.getFields();
+ final int minFieldNumber;
+ final int maxFieldNumber;
+ if (fis.length == 0) {
+ minFieldNumber = 0;
+ maxFieldNumber = 0;
+ } else {
+ minFieldNumber = fis[0].getFieldNumber();
+ maxFieldNumber = fis[fis.length - 1].getFieldNumber();
+ }
+
+ final int numEntries = fis.length;
+
+ int[] buffer = new int[numEntries * INTS_PER_FIELD];
+ Object[] objects = new Object[numEntries * 2];
+
+ int mapFieldCount = 0;
+ int repeatedFieldCount = 0;
+ for (FieldInfo fi : fis) {
+ if (fi.getType() == FieldType.MAP) {
+ mapFieldCount++;
+ } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) {
+ // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
+ // 49 (GROUP_LIST).
+ repeatedFieldCount++;
+ }
+ }
+ int[] mapFieldPositions = mapFieldCount > 0 ? new int[mapFieldCount] : null;
+ int[] repeatedFieldOffsets = repeatedFieldCount > 0 ? new int[repeatedFieldCount] : null;
+ mapFieldCount = 0;
+ repeatedFieldCount = 0;
+
+ int[] checkInitialized = messageInfo.getCheckInitialized();
+ if (checkInitialized == null) {
+ checkInitialized = EMPTY_INT_ARRAY;
+ }
+ int checkInitializedIndex = 0;
+ // Fill in the manifest data from the descriptors.
+ int fieldIndex = 0;
+ for (int bufferIndex = 0; fieldIndex < fis.length; bufferIndex += INTS_PER_FIELD) {
+ final FieldInfo fi = fis[fieldIndex];
+ final int fieldNumber = fi.getFieldNumber();
+
+ // We found the entry for the next field. Store the entry in the manifest for
+ // this field and increment the field index.
+ storeFieldData(fi, buffer, bufferIndex, isProto3, objects);
+
+ // Convert field number to index
+ if (checkInitializedIndex < checkInitialized.length
+ && checkInitialized[checkInitializedIndex] == fieldNumber) {
+ checkInitialized[checkInitializedIndex++] = bufferIndex;
+ }
+
+ if (fi.getType() == FieldType.MAP) {
+ mapFieldPositions[mapFieldCount++] = bufferIndex;
+ } else if (fi.getType().id() >= 18 && fi.getType().id() <= 49) {
+ // Field types of repeated fields are in a consecutive range from 18 (DOUBLE_LIST) to
+ // 49 (GROUP_LIST).
+ repeatedFieldOffsets[repeatedFieldCount++] =
+ (int) UnsafeUtil.objectFieldOffset(fi.getField());
+ }
+
+ fieldIndex++;
+ }
+
+ if (mapFieldPositions == null) {
+ mapFieldPositions = EMPTY_INT_ARRAY;
+ }
+ if (repeatedFieldOffsets == null) {
+ repeatedFieldOffsets = EMPTY_INT_ARRAY;
+ }
+ int[] combined =
+ new int[checkInitialized.length + mapFieldPositions.length + repeatedFieldOffsets.length];
+ System.arraycopy(checkInitialized, 0, combined, 0, checkInitialized.length);
+ System.arraycopy(
+ mapFieldPositions, 0, combined, checkInitialized.length, mapFieldPositions.length);
+ System.arraycopy(
+ repeatedFieldOffsets,
+ 0,
+ combined,
+ checkInitialized.length + mapFieldPositions.length,
+ repeatedFieldOffsets.length);
+
+ return new MessageSchema<T>(
+ buffer,
+ objects,
+ minFieldNumber,
+ maxFieldNumber,
+ messageInfo.getDefaultInstance(),
+ isProto3,
+ /* useCachedSizeField= */ true,
+ combined,
+ checkInitialized.length,
+ checkInitialized.length + mapFieldPositions.length,
+ newInstanceSchema,
+ listFieldSchema,
+ unknownFieldSchema,
+ extensionSchema,
+ mapFieldSchema);
+ }
+
+ private static void storeFieldData(
+ FieldInfo fi, int[] buffer, int bufferIndex, boolean proto3, Object[] objects) {
+ final int fieldOffset;
+ final int typeId;
+ final int presenceMaskShift;
+ final int presenceFieldOffset;
+
+ OneofInfo oneof = fi.getOneof();
+ if (oneof != null) {
+ typeId = fi.getType().id() + ONEOF_TYPE_OFFSET;
+ fieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getValueField());
+ presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(oneof.getCaseField());
+ presenceMaskShift = 0;
+ } else {
+ FieldType type = fi.getType();
+ fieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getField());
+ typeId = type.id();
+ if (!proto3 && !type.isList() && !type.isMap()) {
+ presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getPresenceField());
+ presenceMaskShift = Integer.numberOfTrailingZeros(fi.getPresenceMask());
+ } else {
+ if (fi.getCachedSizeField() == null) {
+ presenceFieldOffset = 0;
+ presenceMaskShift = 0;
+ } else {
+ presenceFieldOffset = (int) UnsafeUtil.objectFieldOffset(fi.getCachedSizeField());
+ presenceMaskShift = 0;
+ }
+ }
+ }
+
+ buffer[bufferIndex] = fi.getFieldNumber();
+ buffer[bufferIndex + 1] =
+ (fi.isEnforceUtf8() ? ENFORCE_UTF8_MASK : 0)
+ | (fi.isRequired() ? REQUIRED_MASK : 0)
+ | (typeId << OFFSET_BITS)
+ | fieldOffset;
+ buffer[bufferIndex + 2] = (presenceMaskShift << OFFSET_BITS) | presenceFieldOffset;
+
+ Object messageFieldClass = fi.getMessageFieldClass();
+ if (fi.getMapDefaultEntry() != null) {
+ objects[bufferIndex / INTS_PER_FIELD * 2] = fi.getMapDefaultEntry();
+ if (messageFieldClass != null) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass;
+ } else if (fi.getEnumVerifier() != null) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier();
+ }
+ } else {
+ if (messageFieldClass != null) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = messageFieldClass;
+ } else if (fi.getEnumVerifier() != null) {
+ objects[bufferIndex / INTS_PER_FIELD * 2 + 1] = fi.getEnumVerifier();
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T newInstance() {
+ return (T) newInstanceSchema.newInstance(defaultInstance);
+ }
+
+ @Override
+ public boolean equals(T message, T other) {
+ final int bufferLength = buffer.length;
+ for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
+ if (!equals(message, other, pos)) {
+ return false;
+ }
+ }
+
+ Object messageUnknown = unknownFieldSchema.getFromMessage(message);
+ Object otherUnknown = unknownFieldSchema.getFromMessage(other);
+ if (!messageUnknown.equals(otherUnknown)) {
+ return false;
+ }
+
+ if (hasExtensions) {
+ FieldSet<?> messageExtensions = extensionSchema.getExtensions(message);
+ FieldSet<?> otherExtensions = extensionSchema.getExtensions(other);
+ return messageExtensions.equals(otherExtensions);
+ }
+ return true;
+ }
+
+ private boolean equals(T message, T other, int pos) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final long offset = offset(typeAndOffset);
+
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ return arePresentForEquals(message, other, pos)
+ && Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset))
+ == Double.doubleToLongBits(UnsafeUtil.getDouble(other, offset));
+ case 1: // FLOAT:
+ return arePresentForEquals(message, other, pos)
+ && Float.floatToIntBits(UnsafeUtil.getFloat(message, offset))
+ == Float.floatToIntBits(UnsafeUtil.getFloat(other, offset));
+ case 2: // INT64:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
+ case 3: // UINT64:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
+ case 4: // INT32:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 5: // FIXED64:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
+ case 6: // FIXED32:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 7: // BOOL:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getBoolean(message, offset) == UnsafeUtil.getBoolean(other, offset);
+ case 8: // STRING:
+ return arePresentForEquals(message, other, pos)
+ && SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ case 9: // MESSAGE:
+ return arePresentForEquals(message, other, pos)
+ && SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ case 10: // BYTES:
+ return arePresentForEquals(message, other, pos)
+ && SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ case 11: // UINT32:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 12: // ENUM:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 13: // SFIXED32:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 14: // SFIXED64:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
+ case 15: // SINT32:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getInt(message, offset) == UnsafeUtil.getInt(other, offset);
+ case 16: // SINT64:
+ return arePresentForEquals(message, other, pos)
+ && UnsafeUtil.getLong(message, offset) == UnsafeUtil.getLong(other, offset);
+ case 17: // GROUP:
+ return arePresentForEquals(message, other, pos)
+ && SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+
+ case 18: // DOUBLE_LIST:
+ case 19: // FLOAT_LIST:
+ case 20: // INT64_LIST:
+ case 21: // UINT64_LIST:
+ case 22: // INT32_LIST:
+ case 23: // FIXED64_LIST:
+ case 24: // FIXED32_LIST:
+ case 25: // BOOL_LIST:
+ case 26: // STRING_LIST:
+ case 27: // MESSAGE_LIST:
+ case 28: // BYTES_LIST:
+ case 29: // UINT32_LIST:
+ case 30: // ENUM_LIST:
+ case 31: // SFIXED32_LIST:
+ case 32: // SFIXED64_LIST:
+ case 33: // SINT32_LIST:
+ case 34: // SINT64_LIST:
+ case 35: // DOUBLE_LIST_PACKED:
+ case 36: // FLOAT_LIST_PACKED:
+ case 37: // INT64_LIST_PACKED:
+ case 38: // UINT64_LIST_PACKED:
+ case 39: // INT32_LIST_PACKED:
+ case 40: // FIXED64_LIST_PACKED:
+ case 41: // FIXED32_LIST_PACKED:
+ case 42: // BOOL_LIST_PACKED:
+ case 43: // UINT32_LIST_PACKED:
+ case 44: // ENUM_LIST_PACKED:
+ case 45: // SFIXED32_LIST_PACKED:
+ case 46: // SFIXED64_LIST_PACKED:
+ case 47: // SINT32_LIST_PACKED:
+ case 48: // SINT64_LIST_PACKED:
+ case 49: // GROUP_LIST:
+ return SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ case 50: // MAP:
+ return SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ case 51: // ONEOF_DOUBLE:
+ case 52: // ONEOF_FLOAT:
+ case 53: // ONEOF_INT64:
+ case 54: // ONEOF_UINT64:
+ case 55: // ONEOF_INT32:
+ case 56: // ONEOF_FIXED64:
+ case 57: // ONEOF_FIXED32:
+ case 58: // ONEOF_BOOL:
+ case 59: // ONEOF_STRING:
+ case 60: // ONEOF_MESSAGE:
+ case 61: // ONEOF_BYTES:
+ case 62: // ONEOF_UINT32:
+ case 63: // ONEOF_ENUM:
+ case 64: // ONEOF_SFIXED32:
+ case 65: // ONEOF_SFIXED64:
+ case 66: // ONEOF_SINT32:
+ case 67: // ONEOF_SINT64:
+ case 68: // ONEOF_GROUP:
+ return isOneofCaseEqual(message, other, pos)
+ && SchemaUtil.safeEquals(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(other, offset));
+ default:
+ // Assume it's an empty entry - just go to the next entry.
+ return true;
+ }
+ }
+
+ @Override
+ public int hashCode(T message) {
+ int hashCode = 0;
+ final int bufferLength = buffer.length;
+ for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final int entryNumber = numberAt(pos);
+
+ final long offset = offset(typeAndOffset);
+
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ hashCode =
+ (hashCode * 53)
+ + Internal.hashLong(
+ Double.doubleToLongBits(UnsafeUtil.getDouble(message, offset)));
+ break;
+ case 1: // FLOAT:
+ hashCode = (hashCode * 53) + Float.floatToIntBits(UnsafeUtil.getFloat(message, offset));
+ break;
+ case 2: // INT64:
+ hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
+ break;
+ case 3: // UINT64:
+ hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
+ break;
+ case 4: // INT32:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 5: // FIXED64:
+ hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
+ break;
+ case 6: // FIXED32:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 7: // BOOL:
+ hashCode = (hashCode * 53) + Internal.hashBoolean(UnsafeUtil.getBoolean(message, offset));
+ break;
+ case 8: // STRING:
+ hashCode = (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode();
+ break;
+ case 9: // MESSAGE:
+ {
+ int protoHash = 37;
+ Object submessage = UnsafeUtil.getObject(message, offset);
+ if (submessage != null) {
+ protoHash = submessage.hashCode();
+ }
+ hashCode = (53 * hashCode) + protoHash;
+ break;
+ }
+ case 10: // BYTES:
+ hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
+ break;
+ case 11: // UINT32:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 12: // ENUM:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 13: // SFIXED32:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 14: // SFIXED64:
+ hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
+ break;
+ case 15: // SINT32:
+ hashCode = (hashCode * 53) + (UnsafeUtil.getInt(message, offset));
+ break;
+ case 16: // SINT64:
+ hashCode = (hashCode * 53) + Internal.hashLong(UnsafeUtil.getLong(message, offset));
+ break;
+
+ case 17: // GROUP:
+ {
+ int protoHash = 37;
+ Object submessage = UnsafeUtil.getObject(message, offset);
+ if (submessage != null) {
+ protoHash = submessage.hashCode();
+ }
+ hashCode = (53 * hashCode) + protoHash;
+ break;
+ }
+ case 18: // DOUBLE_LIST:
+ case 19: // FLOAT_LIST:
+ case 20: // INT64_LIST:
+ case 21: // UINT64_LIST:
+ case 22: // INT32_LIST:
+ case 23: // FIXED64_LIST:
+ case 24: // FIXED32_LIST:
+ case 25: // BOOL_LIST:
+ case 26: // STRING_LIST:
+ case 27: // MESSAGE_LIST:
+ case 28: // BYTES_LIST:
+ case 29: // UINT32_LIST:
+ case 30: // ENUM_LIST:
+ case 31: // SFIXED32_LIST:
+ case 32: // SFIXED64_LIST:
+ case 33: // SINT32_LIST:
+ case 34: // SINT64_LIST:
+ case 35: // DOUBLE_LIST_PACKED:
+ case 36: // FLOAT_LIST_PACKED:
+ case 37: // INT64_LIST_PACKED:
+ case 38: // UINT64_LIST_PACKED:
+ case 39: // INT32_LIST_PACKED:
+ case 40: // FIXED64_LIST_PACKED:
+ case 41: // FIXED32_LIST_PACKED:
+ case 42: // BOOL_LIST_PACKED:
+ case 43: // UINT32_LIST_PACKED:
+ case 44: // ENUM_LIST_PACKED:
+ case 45: // SFIXED32_LIST_PACKED:
+ case 46: // SFIXED64_LIST_PACKED:
+ case 47: // SINT32_LIST_PACKED:
+ case 48: // SINT64_LIST_PACKED:
+ case 49: // GROUP_LIST:
+ hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
+ break;
+ case 50: // MAP:
+ hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode =
+ (hashCode * 53)
+ + Internal.hashLong(Double.doubleToLongBits(oneofDoubleAt(message, offset)));
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Float.floatToIntBits(oneofFloatAt(message, offset));
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashBoolean(oneofBooleanAt(message, offset));
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode =
+ (hashCode * 53) + ((String) UnsafeUtil.getObject(message, offset)).hashCode();
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ Object submessage = UnsafeUtil.getObject(message, offset);
+ hashCode = (53 * hashCode) + submessage.hashCode();
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + UnsafeUtil.getObject(message, offset).hashCode();
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + (oneofIntAt(message, offset));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ hashCode = (hashCode * 53) + Internal.hashLong(oneofLongAt(message, offset));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, entryNumber, pos)) {
+ Object submessage = UnsafeUtil.getObject(message, offset);
+ hashCode = (53 * hashCode) + submessage.hashCode();
+ }
+ break;
+ default:
+ // Assume it's an empty entry - just go to the next entry.
+ break;
+ }
+ }
+
+ hashCode = (hashCode * 53) + unknownFieldSchema.getFromMessage(message).hashCode();
+
+ if (hasExtensions) {
+ hashCode = (hashCode * 53) + extensionSchema.getExtensions(message).hashCode();
+ }
+
+ return hashCode;
+ }
+
+ @Override
+ public void mergeFrom(T message, T other) {
+ if (other == null) {
+ throw new NullPointerException();
+ }
+ for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
+ // A separate method allows for better JIT optimizations
+ mergeSingleField(message, other, i);
+ }
+
+ if (!proto3) {
+ SchemaUtil.mergeUnknownFields(unknownFieldSchema, message, other);
+
+ if (hasExtensions) {
+ SchemaUtil.mergeExtensions(extensionSchema, message, other);
+ }
+ }
+ }
+
+ private void mergeSingleField(T message, T other, int pos) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final long offset = offset(typeAndOffset);
+ final int number = numberAt(pos);
+
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putDouble(message, offset, UnsafeUtil.getDouble(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 1: // FLOAT:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putFloat(message, offset, UnsafeUtil.getFloat(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 2: // INT64:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 3: // UINT64:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 4: // INT32:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 5: // FIXED64:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 6: // FIXED32:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 7: // BOOL:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putBoolean(message, offset, UnsafeUtil.getBoolean(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 8: // STRING:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 9: // MESSAGE:
+ mergeMessage(message, other, pos);
+ break;
+ case 10: // BYTES:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 11: // UINT32:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 12: // ENUM:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 13: // SFIXED32:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 14: // SFIXED64:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 15: // SINT32:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putInt(message, offset, UnsafeUtil.getInt(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 16: // SINT64:
+ if (isFieldPresent(other, pos)) {
+ UnsafeUtil.putLong(message, offset, UnsafeUtil.getLong(other, offset));
+ setFieldPresent(message, pos);
+ }
+ break;
+ case 17: // GROUP:
+ mergeMessage(message, other, pos);
+ break;
+ case 18: // DOUBLE_LIST:
+ case 19: // FLOAT_LIST:
+ case 20: // INT64_LIST:
+ case 21: // UINT64_LIST:
+ case 22: // INT32_LIST:
+ case 23: // FIXED64_LIST:
+ case 24: // FIXED32_LIST:
+ case 25: // BOOL_LIST:
+ case 26: // STRING_LIST:
+ case 27: // MESSAGE_LIST:
+ case 28: // BYTES_LIST:
+ case 29: // UINT32_LIST:
+ case 30: // ENUM_LIST:
+ case 31: // SFIXED32_LIST:
+ case 32: // SFIXED64_LIST:
+ case 33: // SINT32_LIST:
+ case 34: // SINT64_LIST:
+ case 35: // DOUBLE_LIST_PACKED:
+ case 36: // FLOAT_LIST_PACKED:
+ case 37: // INT64_LIST_PACKED:
+ case 38: // UINT64_LIST_PACKED:
+ case 39: // INT32_LIST_PACKED:
+ case 40: // FIXED64_LIST_PACKED:
+ case 41: // FIXED32_LIST_PACKED:
+ case 42: // BOOL_LIST_PACKED:
+ case 43: // UINT32_LIST_PACKED:
+ case 44: // ENUM_LIST_PACKED:
+ case 45: // SFIXED32_LIST_PACKED:
+ case 46: // SFIXED64_LIST_PACKED:
+ case 47: // SINT32_LIST_PACKED:
+ case 48: // SINT64_LIST_PACKED:
+ case 49: // GROUP_LIST:
+ listFieldSchema.mergeListsAt(message, other, offset);
+ break;
+ case 50: // MAP:
+ SchemaUtil.mergeMap(mapFieldSchema, message, other, offset);
+ break;
+ case 51: // ONEOF_DOUBLE:
+ case 52: // ONEOF_FLOAT:
+ case 53: // ONEOF_INT64:
+ case 54: // ONEOF_UINT64:
+ case 55: // ONEOF_INT32:
+ case 56: // ONEOF_FIXED64:
+ case 57: // ONEOF_FIXED32:
+ case 58: // ONEOF_BOOL:
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(other, number, pos)) {
+ UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
+ setOneofPresent(message, number, pos);
+ }
+ break;
+
+ case 60: // ONEOF_MESSAGE:
+ mergeOneofMessage(message, other, pos);
+ break;
+ case 61: // ONEOF_BYTES:
+ case 62: // ONEOF_UINT32:
+ case 63: // ONEOF_ENUM:
+ case 64: // ONEOF_SFIXED32:
+ case 65: // ONEOF_SFIXED64:
+ case 66: // ONEOF_SINT32:
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(other, number, pos)) {
+ UnsafeUtil.putObject(message, offset, UnsafeUtil.getObject(other, offset));
+ setOneofPresent(message, number, pos);
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ mergeOneofMessage(message, other, pos);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void mergeMessage(T message, T other, int pos) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final long offset = offset(typeAndOffset);
+
+ if (!isFieldPresent(other, pos)) {
+ return;
+ }
+
+ Object mine = UnsafeUtil.getObject(message, offset);
+ Object theirs = UnsafeUtil.getObject(other, offset);
+ if (mine != null && theirs != null) {
+ Object merged = Internal.mergeMessage(mine, theirs);
+ UnsafeUtil.putObject(message, offset, merged);
+ setFieldPresent(message, pos);
+ } else if (theirs != null) {
+ UnsafeUtil.putObject(message, offset, theirs);
+ setFieldPresent(message, pos);
+ }
+ }
+
+ private void mergeOneofMessage(T message, T other, int pos) {
+ int typeAndOffset = typeAndOffsetAt(pos);
+ int number = numberAt(pos);
+ long offset = offset(typeAndOffset);
+
+ if (!isOneofPresent(other, number, pos)) {
+ return;
+ }
+
+ Object mine = UnsafeUtil.getObject(message, offset);
+ Object theirs = UnsafeUtil.getObject(other, offset);
+ if (mine != null && theirs != null) {
+ Object merged = Internal.mergeMessage(mine, theirs);
+ UnsafeUtil.putObject(message, offset, merged);
+ setOneofPresent(message, number, pos);
+ } else if (theirs != null) {
+ UnsafeUtil.putObject(message, offset, theirs);
+ setOneofPresent(message, number, pos);
+ }
+ }
+
+ @Override
+ public int getSerializedSize(T message) {
+ return proto3 ? getSerializedSizeProto3(message) : getSerializedSizeProto2(message);
+ }
+
+ @SuppressWarnings("unchecked")
+ private int getSerializedSizeProto2(T message) {
+ int size = 0;
+
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ int currentPresenceFieldOffset = -1;
+ int currentPresenceField = 0;
+ for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(i);
+ final int number = numberAt(i);
+
+ int fieldType = type(typeAndOffset);
+ int presenceMaskAndOffset = 0;
+ int presenceMask = 0;
+ if (fieldType <= 17) {
+ presenceMaskAndOffset = buffer[i + 2];
+ final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
+ presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ if (presenceFieldOffset != currentPresenceFieldOffset) {
+ currentPresenceFieldOffset = presenceFieldOffset;
+ currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
+ }
+ } else if (useCachedSizeField
+ && fieldType >= FieldType.DOUBLE_LIST_PACKED.id()
+ && fieldType <= FieldType.SINT64_LIST_PACKED.id()) {
+ presenceMaskAndOffset = buffer[i + 2] & OFFSET_MASK;
+ }
+
+ final long offset = offset(typeAndOffset);
+
+ switch (fieldType) {
+ case 0: // DOUBLE:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeDoubleSize(number, 0);
+ }
+ break;
+ case 1: // FLOAT:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeFloatSize(number, 0);
+ }
+ break;
+ case 2: // INT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeInt64Size(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 3: // UINT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeUInt64Size(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 4: // INT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeInt32Size(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 5: // FIXED64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeFixed64Size(number, 0);
+ }
+ break;
+ case 6: // FIXED32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeFixed32Size(number, 0);
+ }
+ break;
+ case 7: // BOOL:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeBoolSize(number, true);
+ }
+ break;
+ case 8: // STRING:
+ if ((currentPresenceField & presenceMask) != 0) {
+ Object value = unsafe.getObject(message, offset);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSize(number, (String) value);
+ }
+ }
+ break;
+ case 9: // MESSAGE:
+ if ((currentPresenceField & presenceMask) != 0) {
+ Object value = unsafe.getObject(message, offset);
+ size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
+ }
+ break;
+ case 10: // BYTES:
+ if ((currentPresenceField & presenceMask) != 0) {
+ ByteString value = (ByteString) unsafe.getObject(message, offset);
+ size += CodedOutputStream.computeBytesSize(number, value);
+ }
+ break;
+ case 11: // UINT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeUInt32Size(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 12: // ENUM:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeEnumSize(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 13: // SFIXED32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeSFixed32Size(number, 0);
+ }
+ break;
+ case 14: // SFIXED64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeSFixed64Size(number, 0);
+ }
+ break;
+ case 15: // SINT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeSInt32Size(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 16: // SINT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size += CodedOutputStream.computeSInt64Size(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 17: // GROUP:
+ if ((currentPresenceField & presenceMask) != 0) {
+ size +=
+ CodedOutputStream.computeGroupSize(
+ number,
+ (MessageLite) unsafe.getObject(message, offset),
+ getMessageFieldSchema(i));
+ }
+ break;
+ case 18: // DOUBLE_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed64List(
+ number, (List<?>) unsafe.getObject(message, offset), false);
+ break;
+ case 19: // FLOAT_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed32List(
+ number, (List<?>) unsafe.getObject(message, offset), false);
+ break;
+ case 20: // INT64_LIST:
+ size +=
+ SchemaUtil.computeSizeInt64List(
+ number, (List<Long>) unsafe.getObject(message, offset), false);
+ break;
+ case 21: // UINT64_LIST:
+ size +=
+ SchemaUtil.computeSizeUInt64List(
+ number, (List<Long>) unsafe.getObject(message, offset), false);
+ break;
+ case 22: // INT32_LIST:
+ size +=
+ SchemaUtil.computeSizeInt32List(
+ number, (List<Integer>) unsafe.getObject(message, offset), false);
+ break;
+ case 23: // FIXED64_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed64List(
+ number, (List<?>) unsafe.getObject(message, offset), false);
+ break;
+ case 24: // FIXED32_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed32List(
+ number, (List<?>) unsafe.getObject(message, offset), false);
+ break;
+ case 25: // BOOL_LIST:
+ size +=
+ SchemaUtil.computeSizeBoolList(
+ number, (List<?>) unsafe.getObject(message, offset), false);
+ break;
+ case 26: // STRING_LIST:
+ size +=
+ SchemaUtil.computeSizeStringList(number, (List<?>) unsafe.getObject(message, offset));
+ break;
+ case 27: // MESSAGE_LIST:
+ size +=
+ SchemaUtil.computeSizeMessageList(
+ number, (List<?>) unsafe.getObject(message, offset), getMessageFieldSchema(i));
+ break;
+ case 28: // BYTES_LIST:
+ size +=
+ SchemaUtil.computeSizeByteStringList(
+ number, (List<ByteString>) unsafe.getObject(message, offset));
+ break;
+ case 29: // UINT32_LIST:
+ size +=
+ SchemaUtil.computeSizeUInt32List(
+ number, (List<Integer>) unsafe.getObject(message, offset), false);
+ break;
+ case 30: // ENUM_LIST:
+ size +=
+ SchemaUtil.computeSizeEnumList(
+ number, (List<Integer>) unsafe.getObject(message, offset), false);
+ break;
+ case 31: // SFIXED32_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed32List(
+ number, (List<Integer>) unsafe.getObject(message, offset), false);
+ break;
+ case 32: // SFIXED64_LIST:
+ size +=
+ SchemaUtil.computeSizeFixed64List(
+ number, (List<Long>) unsafe.getObject(message, offset), false);
+ break;
+ case 33: // SINT32_LIST:
+ size +=
+ SchemaUtil.computeSizeSInt32List(
+ number, (List<Integer>) unsafe.getObject(message, offset), false);
+ break;
+ case 34: // SINT64_LIST:
+ size +=
+ SchemaUtil.computeSizeSInt64List(
+ number, (List<Long>) unsafe.getObject(message, offset), false);
+ break;
+ case 35:
+ { // DOUBLE_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Double>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 36:
+ { // FLOAT_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Float>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 37:
+ { // INT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 38:
+ { // UINT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeUInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 39:
+ { // INT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 40:
+ { // FIXED64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 41:
+ { // FIXED32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 42:
+ { // BOOL_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeBoolListNoTag(
+ (List<Boolean>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 43:
+ { // UINT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeUInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 44:
+ { // ENUM_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeEnumListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 45:
+ { // SFIXED32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 46:
+ { // SFIXED64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 47:
+ { // SINT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeSInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 48:
+ { // SINT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeSInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) presenceMaskAndOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 49: // GROUP_LIST:
+ size +=
+ SchemaUtil.computeSizeGroupList(
+ number,
+ (List<MessageLite>) unsafe.getObject(message, offset),
+ getMessageFieldSchema(i));
+ break;
+ case 50: // MAP:
+ // TODO(dweis): Use schema cache.
+ size +=
+ mapFieldSchema.getSerializedSize(
+ number, unsafe.getObject(message, offset), getMapFieldDefaultEntry(i));
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeDoubleSize(number, 0);
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFloatSize(number, 0);
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFixed64Size(number, 0);
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFixed32Size(number, 0);
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeBoolSize(number, true);
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, number, i)) {
+ Object value = unsafe.getObject(message, offset);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSize(number, (String) value);
+ }
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, i)) {
+ Object value = unsafe.getObject(message, offset);
+ size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, number, i)) {
+ size +=
+ CodedOutputStream.computeBytesSize(
+ number, (ByteString) unsafe.getObject(message, offset));
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSFixed32Size(number, 0);
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSFixed64Size(number, 0);
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, number, i)) {
+ size +=
+ CodedOutputStream.computeGroupSize(
+ number,
+ (MessageLite) unsafe.getObject(message, offset),
+ getMessageFieldSchema(i));
+ }
+ break;
+ default:
+ // Assume it's an empty entry.
+ }
+ }
+
+ size += getUnknownFieldsSerializedSize(unknownFieldSchema, message);
+
+ if (hasExtensions) {
+ size += extensionSchema.getExtensions(message).getSerializedSize();
+ }
+
+ return size;
+ }
+
+ private int getSerializedSizeProto3(T message) {
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ int size = 0;
+ for (int i = 0; i < buffer.length; i += INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(i);
+ final int fieldType = type(typeAndOffset);
+ final int number = numberAt(i);
+
+ final long offset = offset(typeAndOffset);
+ final int cachedSizeOffset =
+ fieldType >= FieldType.DOUBLE_LIST_PACKED.id()
+ && fieldType <= FieldType.SINT64_LIST_PACKED.id()
+ ? buffer[i + 2] & OFFSET_MASK
+ : 0;
+
+ switch (fieldType) {
+ case 0: // DOUBLE:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeDoubleSize(number, 0);
+ }
+ break;
+ case 1: // FLOAT:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeFloatSize(number, 0);
+ }
+ break;
+ case 2: // INT64:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeInt64Size(number, UnsafeUtil.getLong(message, offset));
+ }
+ break;
+ case 3: // UINT64:
+ if (isFieldPresent(message, i)) {
+ size +=
+ CodedOutputStream.computeUInt64Size(number, UnsafeUtil.getLong(message, offset));
+ }
+ break;
+ case 4: // INT32:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeInt32Size(number, UnsafeUtil.getInt(message, offset));
+ }
+ break;
+ case 5: // FIXED64:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeFixed64Size(number, 0);
+ }
+ break;
+ case 6: // FIXED32:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeFixed32Size(number, 0);
+ }
+ break;
+ case 7: // BOOL:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeBoolSize(number, true);
+ }
+ break;
+ case 8: // STRING:
+ if (isFieldPresent(message, i)) {
+ Object value = UnsafeUtil.getObject(message, offset);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSize(number, (String) value);
+ }
+ }
+ break;
+ case 9: // MESSAGE:
+ if (isFieldPresent(message, i)) {
+ Object value = UnsafeUtil.getObject(message, offset);
+ size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
+ }
+ break;
+ case 10: // BYTES:
+ if (isFieldPresent(message, i)) {
+ ByteString value = (ByteString) UnsafeUtil.getObject(message, offset);
+ size += CodedOutputStream.computeBytesSize(number, value);
+ }
+ break;
+ case 11: // UINT32:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeUInt32Size(number, UnsafeUtil.getInt(message, offset));
+ }
+ break;
+ case 12: // ENUM:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeEnumSize(number, UnsafeUtil.getInt(message, offset));
+ }
+ break;
+ case 13: // SFIXED32:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeSFixed32Size(number, 0);
+ }
+ break;
+ case 14: // SFIXED64:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeSFixed64Size(number, 0);
+ }
+ break;
+ case 15: // SINT32:
+ if (isFieldPresent(message, i)) {
+ size += CodedOutputStream.computeSInt32Size(number, UnsafeUtil.getInt(message, offset));
+ }
+ break;
+ case 16: // SINT64:
+ if (isFieldPresent(message, i)) {
+ size +=
+ CodedOutputStream.computeSInt64Size(number, UnsafeUtil.getLong(message, offset));
+ }
+ break;
+ case 17: // GROUP:
+ if (isFieldPresent(message, i)) {
+ size +=
+ CodedOutputStream.computeGroupSize(
+ number,
+ (MessageLite) UnsafeUtil.getObject(message, offset),
+ getMessageFieldSchema(i));
+ }
+ break;
+ case 18: // DOUBLE_LIST:
+ size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
+ break;
+ case 19: // FLOAT_LIST:
+ size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
+ break;
+ case 20: // INT64_LIST:
+ size +=
+ SchemaUtil.computeSizeInt64List(number, (List<Long>) listAt(message, offset), false);
+ break;
+ case 21: // UINT64_LIST:
+ size +=
+ SchemaUtil.computeSizeUInt64List(number, (List<Long>) listAt(message, offset), false);
+ break;
+ case 22: // INT32_LIST:
+ size +=
+ SchemaUtil.computeSizeInt32List(
+ number, (List<Integer>) listAt(message, offset), false);
+ break;
+ case 23: // FIXED64_LIST:
+ size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
+ break;
+ case 24: // FIXED32_LIST:
+ size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
+ break;
+ case 25: // BOOL_LIST:
+ size += SchemaUtil.computeSizeBoolList(number, listAt(message, offset), false);
+ break;
+ case 26: // STRING_LIST:
+ size += SchemaUtil.computeSizeStringList(number, listAt(message, offset));
+ break;
+ case 27: // MESSAGE_LIST:
+ size +=
+ SchemaUtil.computeSizeMessageList(
+ number, listAt(message, offset), getMessageFieldSchema(i));
+ break;
+ case 28: // BYTES_LIST:
+ size +=
+ SchemaUtil.computeSizeByteStringList(
+ number, (List<ByteString>) listAt(message, offset));
+ break;
+ case 29: // UINT32_LIST:
+ size +=
+ SchemaUtil.computeSizeUInt32List(
+ number, (List<Integer>) listAt(message, offset), false);
+ break;
+ case 30: // ENUM_LIST:
+ size +=
+ SchemaUtil.computeSizeEnumList(
+ number, (List<Integer>) listAt(message, offset), false);
+ break;
+ case 31: // SFIXED32_LIST:
+ size += SchemaUtil.computeSizeFixed32List(number, listAt(message, offset), false);
+ break;
+ case 32: // SFIXED64_LIST:
+ size += SchemaUtil.computeSizeFixed64List(number, listAt(message, offset), false);
+ break;
+ case 33: // SINT32_LIST:
+ size +=
+ SchemaUtil.computeSizeSInt32List(
+ number, (List<Integer>) listAt(message, offset), false);
+ break;
+ case 34: // SINT64_LIST:
+ size +=
+ SchemaUtil.computeSizeSInt64List(number, (List<Long>) listAt(message, offset), false);
+ break;
+ case 35:
+ { // DOUBLE_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Double>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 36:
+ { // FLOAT_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Float>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 37:
+ { // INT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 38:
+ { // UINT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeUInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 39:
+ { // INT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 40:
+ { // FIXED64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 41:
+ { // FIXED32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 42:
+ { // BOOL_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeBoolListNoTag(
+ (List<Boolean>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 43:
+ { // UINT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeUInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 44:
+ { // ENUM_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeEnumListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 45:
+ { // SFIXED32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 46:
+ { // SFIXED64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeFixed64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 47:
+ { // SINT32_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeSInt32ListNoTag(
+ (List<Integer>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 48:
+ { // SINT64_LIST_PACKED:
+ int fieldSize =
+ SchemaUtil.computeSizeSInt64ListNoTag(
+ (List<Long>) unsafe.getObject(message, offset));
+ if (fieldSize > 0) {
+ if (useCachedSizeField) {
+ unsafe.putInt(message, (long) cachedSizeOffset, fieldSize);
+ }
+ size +=
+ CodedOutputStream.computeTagSize(number)
+ + CodedOutputStream.computeUInt32SizeNoTag(fieldSize)
+ + fieldSize;
+ }
+ break;
+ }
+ case 49: // GROUP_LIST:
+ size +=
+ SchemaUtil.computeSizeGroupList(
+ number, (List<MessageLite>) listAt(message, offset), getMessageFieldSchema(i));
+ break;
+ case 50: // MAP:
+ // TODO(dweis): Use schema cache.
+ size +=
+ mapFieldSchema.getSerializedSize(
+ number, UnsafeUtil.getObject(message, offset), getMapFieldDefaultEntry(i));
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeDoubleSize(number, 0);
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFloatSize(number, 0);
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeUInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFixed64Size(number, 0);
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeFixed32Size(number, 0);
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeBoolSize(number, true);
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, number, i)) {
+ Object value = UnsafeUtil.getObject(message, offset);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSize(number, (ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSize(number, (String) value);
+ }
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, i)) {
+ Object value = UnsafeUtil.getObject(message, offset);
+ size += SchemaUtil.computeSizeMessage(number, value, getMessageFieldSchema(i));
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, number, i)) {
+ size +=
+ CodedOutputStream.computeBytesSize(
+ number, (ByteString) UnsafeUtil.getObject(message, offset));
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeUInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeEnumSize(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSFixed32Size(number, 0);
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSFixed64Size(number, 0);
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSInt32Size(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, number, i)) {
+ size += CodedOutputStream.computeSInt64Size(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, number, i)) {
+ size +=
+ CodedOutputStream.computeGroupSize(
+ number,
+ (MessageLite) UnsafeUtil.getObject(message, offset),
+ getMessageFieldSchema(i));
+ }
+ break;
+ default:
+ // Assume it's an empty entry.
+ }
+ }
+
+ size += getUnknownFieldsSerializedSize(unknownFieldSchema, message);
+
+ return size;
+ }
+
+ private <UT, UB> int getUnknownFieldsSerializedSize(
+ UnknownFieldSchema<UT, UB> schema, T message) {
+ UT unknowns = schema.getFromMessage(message);
+ return schema.getSerializedSize(unknowns);
+ }
+
+ private static List<?> listAt(Object message, long offset) {
+ return (List<?>) UnsafeUtil.getObject(message, offset);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ // TODO(nathanmittler): Consider serializing oneof fields last so that only one entry per
+ // oneof is actually serialized. This would mean that we would violate the serialization order
+ // contract. It should also be noted that Go currently does this.
+ public void writeTo(T message, Writer writer) throws IOException {
+ if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
+ writeFieldsInDescendingOrder(message, writer);
+ } else {
+ if (proto3) {
+ writeFieldsInAscendingOrderProto3(message, writer);
+ } else {
+ writeFieldsInAscendingOrderProto2(message, writer);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void writeFieldsInAscendingOrderProto2(T message, Writer writer) throws IOException {
+ Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
+ Map.Entry nextExtension = null;
+ if (hasExtensions) {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ if (!extensions.isEmpty()) {
+ extensionIterator = extensions.iterator();
+ nextExtension = extensionIterator.next();
+ }
+ }
+ int currentPresenceFieldOffset = -1;
+ int currentPresenceField = 0;
+ final int bufferLength = buffer.length;
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final int number = numberAt(pos);
+ final int fieldType = type(typeAndOffset);
+
+ int presenceMaskAndOffset = 0;
+ int presenceMask = 0;
+ if (!proto3 && fieldType <= 17) {
+ presenceMaskAndOffset = buffer[pos + 2];
+ final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
+ if (presenceFieldOffset != currentPresenceFieldOffset) {
+ currentPresenceFieldOffset = presenceFieldOffset;
+ currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
+ }
+ presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ }
+
+ // Write any extensions that need to be written before the current field.
+ while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+ final long offset = offset(typeAndOffset);
+
+ switch (fieldType) {
+ case 0: // DOUBLE:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeDouble(number, doubleAt(message, offset));
+ }
+ break;
+ case 1: // FLOAT:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeFloat(number, floatAt(message, offset));
+ }
+ break;
+ case 2: // INT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeInt64(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 3: // UINT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeUInt64(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 4: // INT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeInt32(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 5: // FIXED64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeFixed64(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 6: // FIXED32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeFixed32(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 7: // BOOL:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeBool(number, booleanAt(message, offset));
+ }
+ break;
+ case 8: // STRING:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writeString(number, unsafe.getObject(message, offset), writer);
+ }
+ break;
+ case 9: // MESSAGE:
+ if ((currentPresenceField & presenceMask) != 0) {
+ Object value = unsafe.getObject(message, offset);
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 10: // BYTES:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset));
+ }
+ break;
+ case 11: // UINT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeUInt32(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 12: // ENUM:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeEnum(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 13: // SFIXED32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeSFixed32(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 14: // SFIXED64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeSFixed64(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 15: // SINT32:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeSInt32(number, unsafe.getInt(message, offset));
+ }
+ break;
+ case 16: // SINT64:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeSInt64(number, unsafe.getLong(message, offset));
+ }
+ break;
+ case 17: // GROUP:
+ if ((currentPresenceField & presenceMask) != 0) {
+ writer.writeGroup(
+ number, unsafe.getObject(message, offset), getMessageFieldSchema(pos));
+ }
+ break;
+ case 18: // DOUBLE_LIST:
+ SchemaUtil.writeDoubleList(
+ numberAt(pos), (List<Double>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 19: // FLOAT_LIST:
+ SchemaUtil.writeFloatList(
+ numberAt(pos), (List<Float>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 20: // INT64_LIST:
+ SchemaUtil.writeInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 21: // UINT64_LIST:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 22: // INT32_LIST:
+ SchemaUtil.writeInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 23: // FIXED64_LIST:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 24: // FIXED32_LIST:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 25: // BOOL_LIST:
+ SchemaUtil.writeBoolList(
+ numberAt(pos), (List<Boolean>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 26: // STRING_LIST:
+ SchemaUtil.writeStringList(
+ numberAt(pos), (List<String>) unsafe.getObject(message, offset), writer);
+ break;
+ case 27: // MESSAGE_LIST:
+ SchemaUtil.writeMessageList(
+ numberAt(pos),
+ (List<?>) unsafe.getObject(message, offset),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 28: // BYTES_LIST:
+ SchemaUtil.writeBytesList(
+ numberAt(pos), (List<ByteString>) unsafe.getObject(message, offset), writer);
+ break;
+ case 29: // UINT32_LIST:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 30: // ENUM_LIST:
+ SchemaUtil.writeEnumList(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 31: // SFIXED32_LIST:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 32: // SFIXED64_LIST:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 33: // SINT32_LIST:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 34: // SINT64_LIST:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, false);
+ break;
+ case 35: // DOUBLE_LIST_PACKED:
+ // TODO(xiaofeng): Make use of cached field size to speed up serialization.
+ SchemaUtil.writeDoubleList(
+ numberAt(pos), (List<Double>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 36: // FLOAT_LIST_PACKED:
+ SchemaUtil.writeFloatList(
+ numberAt(pos), (List<Float>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 37: // INT64_LIST_PACKED:
+ SchemaUtil.writeInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 38: // UINT64_LIST_PACKED:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 39: // INT32_LIST_PACKED:
+ SchemaUtil.writeInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 40: // FIXED64_LIST_PACKED:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 41: // FIXED32_LIST_PACKED:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+
+ break;
+ case 42: // BOOL_LIST_PACKED:
+ SchemaUtil.writeBoolList(
+ numberAt(pos), (List<Boolean>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 43: // UINT32_LIST_PACKED:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 44: // ENUM_LIST_PACKED:
+ SchemaUtil.writeEnumList(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 45: // SFIXED32_LIST_PACKED:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 46: // SFIXED64_LIST_PACKED:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 47: // SINT32_LIST_PACKED:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos), (List<Integer>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 48: // SINT64_LIST_PACKED:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos), (List<Long>) unsafe.getObject(message, offset), writer, true);
+ break;
+ case 49: // GROUP_LIST:
+ SchemaUtil.writeGroupList(
+ numberAt(pos),
+ (List<?>) unsafe.getObject(message, offset),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 50: // MAP:
+ // TODO(dweis): Use schema cache.
+ writeMapHelper(writer, number, unsafe.getObject(message, offset), pos);
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeDouble(number, oneofDoubleAt(message, offset));
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFloat(number, oneofFloatAt(message, offset));
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt64(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt64(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt32(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed64(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed32(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBool(number, oneofBooleanAt(message, offset));
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, number, pos)) {
+ writeString(number, unsafe.getObject(message, offset), writer);
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, pos)) {
+ Object value = unsafe.getObject(message, offset);
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBytes(number, (ByteString) unsafe.getObject(message, offset));
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt32(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeEnum(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed32(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed64(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt32(number, oneofIntAt(message, offset));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt64(number, oneofLongAt(message, offset));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeGroup(
+ number, unsafe.getObject(message, offset), getMessageFieldSchema(pos));
+ }
+ break;
+ default:
+ // Assume it's an empty entry - just go to the next entry.
+ break;
+ }
+ }
+ while (nextExtension != null) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+ writeUnknownInMessageTo(unknownFieldSchema, message, writer);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void writeFieldsInAscendingOrderProto3(T message, Writer writer) throws IOException {
+ Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
+ Map.Entry nextExtension = null;
+ if (hasExtensions) {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ if (!extensions.isEmpty()) {
+ extensionIterator = extensions.iterator();
+ nextExtension = extensionIterator.next();
+ }
+ }
+
+ final int bufferLength = buffer.length;
+ for (int pos = 0; pos < bufferLength; pos += INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final int number = numberAt(pos);
+
+ // Write any extensions that need to be written before the current field.
+ while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) <= number) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ if (isFieldPresent(message, pos)) {
+ writer.writeDouble(number, doubleAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 1: // FLOAT:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFloat(number, floatAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 2: // INT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 3: // UINT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeUInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 4: // INT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 5: // FIXED64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFixed64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 6: // FIXED32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFixed32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 7: // BOOL:
+ if (isFieldPresent(message, pos)) {
+ writer.writeBool(number, booleanAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 8: // STRING:
+ if (isFieldPresent(message, pos)) {
+ writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
+ }
+ break;
+ case 9: // MESSAGE:
+ if (isFieldPresent(message, pos)) {
+ Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 10: // BYTES:
+ if (isFieldPresent(message, pos)) {
+ writer.writeBytes(
+ number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
+ }
+ break;
+ case 11: // UINT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeUInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 12: // ENUM:
+ if (isFieldPresent(message, pos)) {
+ writer.writeEnum(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 13: // SFIXED32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSFixed32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 14: // SFIXED64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSFixed64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 15: // SINT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 16: // SINT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 17: // GROUP:
+ if (isFieldPresent(message, pos)) {
+ writer.writeGroup(
+ number,
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ getMessageFieldSchema(pos));
+ }
+ break;
+ case 18: // DOUBLE_LIST:
+ SchemaUtil.writeDoubleList(
+ numberAt(pos),
+ (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 19: // FLOAT_LIST:
+ SchemaUtil.writeFloatList(
+ numberAt(pos),
+ (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 20: // INT64_LIST:
+ SchemaUtil.writeInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 21: // UINT64_LIST:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 22: // INT32_LIST:
+ SchemaUtil.writeInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 23: // FIXED64_LIST:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 24: // FIXED32_LIST:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 25: // BOOL_LIST:
+ SchemaUtil.writeBoolList(
+ numberAt(pos),
+ (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 26: // STRING_LIST:
+ SchemaUtil.writeStringList(
+ numberAt(pos),
+ (List<String>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer);
+ break;
+ case 27: // MESSAGE_LIST:
+ SchemaUtil.writeMessageList(
+ numberAt(pos),
+ (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 28: // BYTES_LIST:
+ SchemaUtil.writeBytesList(
+ numberAt(pos),
+ (List<ByteString>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer);
+ break;
+ case 29: // UINT32_LIST:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 30: // ENUM_LIST:
+ SchemaUtil.writeEnumList(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 31: // SFIXED32_LIST:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 32: // SFIXED64_LIST:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 33: // SINT32_LIST:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 34: // SINT64_LIST:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 35: // DOUBLE_LIST_PACKED:
+ // TODO(xiaofeng): Make use of cached field size to speed up serialization.
+ SchemaUtil.writeDoubleList(
+ numberAt(pos),
+ (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 36: // FLOAT_LIST_PACKED:
+ SchemaUtil.writeFloatList(
+ numberAt(pos),
+ (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 37: // INT64_LIST_PACKED:
+ SchemaUtil.writeInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 38: // UINT64_LIST_PACKED:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 39: // INT32_LIST_PACKED:
+ SchemaUtil.writeInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 40: // FIXED64_LIST_PACKED:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 41: // FIXED32_LIST_PACKED:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+
+ break;
+ case 42: // BOOL_LIST_PACKED:
+ SchemaUtil.writeBoolList(
+ numberAt(pos),
+ (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 43: // UINT32_LIST_PACKED:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 44: // ENUM_LIST_PACKED:
+ SchemaUtil.writeEnumList(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 45: // SFIXED32_LIST_PACKED:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 46: // SFIXED64_LIST_PACKED:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 47: // SINT32_LIST_PACKED:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 48: // SINT64_LIST_PACKED:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 49: // GROUP_LIST:
+ SchemaUtil.writeGroupList(
+ numberAt(pos),
+ (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 50: // MAP:
+ // TODO(dweis): Use schema cache.
+ writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos);
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, number, pos)) {
+ writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, pos)) {
+ Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBytes(
+ number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeGroup(
+ number,
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ getMessageFieldSchema(pos));
+ }
+ break;
+ default:
+ // Assume it's an empty entry - just go to the next entry.
+ break;
+ }
+ }
+ while (nextExtension != null) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+ writeUnknownInMessageTo(unknownFieldSchema, message, writer);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void writeFieldsInDescendingOrder(T message, Writer writer) throws IOException {
+ writeUnknownInMessageTo(unknownFieldSchema, message, writer);
+
+ Iterator<? extends Map.Entry<?, ?>> extensionIterator = null;
+ Map.Entry nextExtension = null;
+ if (hasExtensions) {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ if (!extensions.isEmpty()) {
+ extensionIterator = extensions.descendingIterator();
+ nextExtension = extensionIterator.next();
+ }
+ }
+
+ for (int pos = buffer.length - INTS_PER_FIELD; pos >= 0; pos -= INTS_PER_FIELD) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final int number = numberAt(pos);
+
+ // Write any extensions that need to be written before the current field.
+ while (nextExtension != null && extensionSchema.extensionNumber(nextExtension) > number) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ if (isFieldPresent(message, pos)) {
+ writer.writeDouble(number, doubleAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 1: // FLOAT:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFloat(number, floatAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 2: // INT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 3: // UINT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeUInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 4: // INT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 5: // FIXED64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFixed64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 6: // FIXED32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeFixed32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 7: // BOOL:
+ if (isFieldPresent(message, pos)) {
+ writer.writeBool(number, booleanAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 8: // STRING:
+ if (isFieldPresent(message, pos)) {
+ writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
+ }
+ break;
+ case 9: // MESSAGE:
+ if (isFieldPresent(message, pos)) {
+ Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 10: // BYTES:
+ if (isFieldPresent(message, pos)) {
+ writer.writeBytes(
+ number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
+ }
+ break;
+ case 11: // UINT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeUInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 12: // ENUM:
+ if (isFieldPresent(message, pos)) {
+ writer.writeEnum(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 13: // SFIXED32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSFixed32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 14: // SFIXED64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSFixed64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 15: // SINT32:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSInt32(number, intAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 16: // SINT64:
+ if (isFieldPresent(message, pos)) {
+ writer.writeSInt64(number, longAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 17: // GROUP:
+ if (isFieldPresent(message, pos)) {
+ writer.writeGroup(
+ number,
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ getMessageFieldSchema(pos));
+ }
+ break;
+ case 18: // DOUBLE_LIST:
+ SchemaUtil.writeDoubleList(
+ numberAt(pos),
+ (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 19: // FLOAT_LIST:
+ SchemaUtil.writeFloatList(
+ numberAt(pos),
+ (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 20: // INT64_LIST:
+ SchemaUtil.writeInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 21: // UINT64_LIST:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 22: // INT32_LIST:
+ SchemaUtil.writeInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 23: // FIXED64_LIST:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 24: // FIXED32_LIST:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 25: // BOOL_LIST:
+ SchemaUtil.writeBoolList(
+ numberAt(pos),
+ (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 26: // STRING_LIST:
+ SchemaUtil.writeStringList(
+ numberAt(pos),
+ (List<String>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer);
+ break;
+ case 27: // MESSAGE_LIST:
+ SchemaUtil.writeMessageList(
+ numberAt(pos),
+ (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 28: // BYTES_LIST:
+ SchemaUtil.writeBytesList(
+ numberAt(pos),
+ (List<ByteString>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer);
+ break;
+ case 29: // UINT32_LIST:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 30: // ENUM_LIST:
+ SchemaUtil.writeEnumList(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 31: // SFIXED32_LIST:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 32: // SFIXED64_LIST:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 33: // SINT32_LIST:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 34: // SINT64_LIST:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ false);
+ break;
+ case 35: // DOUBLE_LIST_PACKED:
+ SchemaUtil.writeDoubleList(
+ numberAt(pos),
+ (List<Double>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 36: // FLOAT_LIST_PACKED:
+ SchemaUtil.writeFloatList(
+ numberAt(pos),
+ (List<Float>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 37: // INT64_LIST_PACKED:
+ SchemaUtil.writeInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 38: // UINT64_LIST_PACKED:
+ SchemaUtil.writeUInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 39: // INT32_LIST_PACKED:
+ SchemaUtil.writeInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 40: // FIXED64_LIST_PACKED:
+ SchemaUtil.writeFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 41: // FIXED32_LIST_PACKED:
+ SchemaUtil.writeFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+
+ break;
+ case 42: // BOOL_LIST_PACKED:
+ SchemaUtil.writeBoolList(
+ numberAt(pos),
+ (List<Boolean>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 43: // UINT32_LIST_PACKED:
+ SchemaUtil.writeUInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 44: // ENUM_LIST_PACKED:
+ SchemaUtil.writeEnumList(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 45: // SFIXED32_LIST_PACKED:
+ SchemaUtil.writeSFixed32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 46: // SFIXED64_LIST_PACKED:
+ SchemaUtil.writeSFixed64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 47: // SINT32_LIST_PACKED:
+ SchemaUtil.writeSInt32List(
+ numberAt(pos),
+ (List<Integer>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 48: // SINT64_LIST_PACKED:
+ SchemaUtil.writeSInt64List(
+ numberAt(pos),
+ (List<Long>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ true);
+ break;
+ case 49: // GROUP_LIST:
+ SchemaUtil.writeGroupList(
+ numberAt(pos),
+ (List<?>) UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ writer,
+ getMessageFieldSchema(pos));
+ break;
+ case 50: // MAP:
+ // TODO(dweis): Use schema cache.
+ writeMapHelper(writer, number, UnsafeUtil.getObject(message, offset(typeAndOffset)), pos);
+ break;
+ case 51: // ONEOF_DOUBLE:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeDouble(number, oneofDoubleAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFloat(number, oneofFloatAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 54: // ONEOF_UINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBool(number, oneofBooleanAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (isOneofPresent(message, number, pos)) {
+ writeString(number, UnsafeUtil.getObject(message, offset(typeAndOffset)), writer);
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, pos)) {
+ Object value = UnsafeUtil.getObject(message, offset(typeAndOffset));
+ writer.writeMessage(number, value, getMessageFieldSchema(pos));
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeBytes(
+ number, (ByteString) UnsafeUtil.getObject(message, offset(typeAndOffset)));
+ }
+ break;
+ case 62: // ONEOF_UINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeUInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeEnum(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 64: // ONEOF_SFIXED32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 65: // ONEOF_SFIXED64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSFixed64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt32(number, oneofIntAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeSInt64(number, oneofLongAt(message, offset(typeAndOffset)));
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (isOneofPresent(message, number, pos)) {
+ writer.writeGroup(
+ number,
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ getMessageFieldSchema(pos));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ while (nextExtension != null) {
+ extensionSchema.serializeExtension(writer, nextExtension);
+ nextExtension = extensionIterator.hasNext() ? extensionIterator.next() : null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <K, V> void writeMapHelper(Writer writer, int number, Object mapField, int pos)
+ throws IOException {
+ if (mapField != null) {
+ writer.writeMap(
+ number,
+ (MapEntryLite.Metadata<K, V>) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos)),
+ (Map<K, V>) mapFieldSchema.forMapData(mapField));
+ }
+ }
+
+ private <UT, UB> void writeUnknownInMessageTo(
+ UnknownFieldSchema<UT, UB> schema, T message, Writer writer) throws IOException {
+ schema.writeTo(schema.getFromMessage(message), writer);
+ }
+
+ @Override
+ public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ if (extensionRegistry == null) {
+ throw new NullPointerException();
+ }
+ mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry);
+ }
+
+ /**
+ * A helper method for wildcard capture of {@code unknownFieldSchema}. See:
+ * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
+ */
+ private <UT, UB, ET extends FieldDescriptorLite<ET>> void mergeFromHelper(
+ UnknownFieldSchema<UT, UB> unknownFieldSchema,
+ ExtensionSchema<ET> extensionSchema,
+ T message,
+ Reader reader,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ UB unknownFields = null;
+ FieldSet<ET> extensions = null;
+ try {
+ while (true) {
+ final int number = reader.getFieldNumber();
+ final int pos = positionForFieldNumber(number);
+ if (pos < 0) {
+ if (number == Reader.READ_DONE) {
+ return;
+ }
+ // Check if it's an extension.
+ Object extension =
+ !hasExtensions
+ ? null
+ : extensionSchema.findExtensionByNumber(
+ extensionRegistry, defaultInstance, number);
+ if (extension != null) {
+ if (extensions == null) {
+ extensions = extensionSchema.getMutableExtensions(message);
+ }
+ unknownFields =
+ extensionSchema.parseExtension(
+ reader,
+ extension,
+ extensionRegistry,
+ extensions,
+ unknownFields,
+ unknownFieldSchema);
+ continue;
+ }
+ if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) {
+ if (reader.skipField()) {
+ continue;
+ }
+ } else {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ }
+ // Unknown field.
+ if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
+ continue;
+ }
+ }
+ // Done reading.
+ return;
+ }
+ final int typeAndOffset = typeAndOffsetAt(pos);
+
+ try {
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ UnsafeUtil.putDouble(message, offset(typeAndOffset), reader.readDouble());
+ setFieldPresent(message, pos);
+ break;
+ case 1: // FLOAT:
+ UnsafeUtil.putFloat(message, offset(typeAndOffset), reader.readFloat());
+ setFieldPresent(message, pos);
+ break;
+ case 2: // INT64:
+ UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readInt64());
+ setFieldPresent(message, pos);
+ break;
+ case 3: // UINT64:
+ UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readUInt64());
+ setFieldPresent(message, pos);
+ break;
+ case 4: // INT32:
+ UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readInt32());
+ setFieldPresent(message, pos);
+ break;
+ case 5: // FIXED64:
+ UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readFixed64());
+ setFieldPresent(message, pos);
+ break;
+ case 6: // FIXED32:
+ UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readFixed32());
+ setFieldPresent(message, pos);
+ break;
+ case 7: // BOOL:
+ UnsafeUtil.putBoolean(message, offset(typeAndOffset), reader.readBool());
+ setFieldPresent(message, pos);
+ break;
+ case 8: // STRING:
+ readString(message, typeAndOffset, reader);
+ setFieldPresent(message, pos);
+ break;
+ case 9:
+ { // MESSAGE:
+ if (isFieldPresent(message, pos)) {
+ Object mergedResult =
+ Internal.mergeMessage(
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ reader.readMessageBySchemaWithCheck(
+ (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
+ UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
+ } else {
+ UnsafeUtil.putObject(
+ message,
+ offset(typeAndOffset),
+ reader.readMessageBySchemaWithCheck(
+ (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
+ setFieldPresent(message, pos);
+ }
+ break;
+ }
+ case 10: // BYTES:
+ UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
+ setFieldPresent(message, pos);
+ break;
+ case 11: // UINT32:
+ UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readUInt32());
+ setFieldPresent(message, pos);
+ break;
+ case 12: // ENUM:
+ {
+ int enumValue = reader.readEnum();
+ EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
+ if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
+ UnsafeUtil.putInt(message, offset(typeAndOffset), enumValue);
+ setFieldPresent(message, pos);
+ } else {
+ unknownFields =
+ SchemaUtil.storeUnknownEnum(
+ number, enumValue, unknownFields, unknownFieldSchema);
+ }
+ break;
+ }
+ case 13: // SFIXED32:
+ UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSFixed32());
+ setFieldPresent(message, pos);
+ break;
+ case 14: // SFIXED64:
+ UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSFixed64());
+ setFieldPresent(message, pos);
+ break;
+ case 15: // SINT32:
+ UnsafeUtil.putInt(message, offset(typeAndOffset), reader.readSInt32());
+ setFieldPresent(message, pos);
+ break;
+ case 16: // SINT64:
+ UnsafeUtil.putLong(message, offset(typeAndOffset), reader.readSInt64());
+ setFieldPresent(message, pos);
+ break;
+ case 17:
+ { // GROUP:
+ if (isFieldPresent(message, pos)) {
+ Object mergedResult =
+ Internal.mergeMessage(
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ reader.readGroupBySchemaWithCheck(
+ (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
+ UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
+ } else {
+ UnsafeUtil.putObject(
+ message,
+ offset(typeAndOffset),
+ reader.readGroupBySchemaWithCheck(
+ (Schema<T>) getMessageFieldSchema(pos), extensionRegistry));
+ setFieldPresent(message, pos);
+ }
+ break;
+ }
+ case 18: // DOUBLE_LIST:
+ reader.readDoubleList(
+ listFieldSchema.<Double>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 19: // FLOAT_LIST:
+ reader.readFloatList(
+ listFieldSchema.<Float>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 20: // INT64_LIST:
+ reader.readInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 21: // UINT64_LIST:
+ reader.readUInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 22: // INT32_LIST:
+ reader.readInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 23: // FIXED64_LIST:
+ reader.readFixed64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 24: // FIXED32_LIST:
+ reader.readFixed32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 25: // BOOL_LIST:
+ reader.readBoolList(
+ listFieldSchema.<Boolean>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 26: // STRING_LIST:
+ readStringList(message, typeAndOffset, reader);
+ break;
+ case 27:
+ { // MESSAGE_LIST:
+ readMessageList(
+ message,
+ typeAndOffset,
+ reader,
+ (Schema<T>) getMessageFieldSchema(pos),
+ extensionRegistry);
+ break;
+ }
+ case 28: // BYTES_LIST:
+ reader.readBytesList(
+ listFieldSchema.<ByteString>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 29: // UINT32_LIST:
+ reader.readUInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 30: // ENUM_LIST:
+ {
+ List<Integer> enumList =
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset));
+ reader.readEnumList(enumList);
+ unknownFields =
+ SchemaUtil.filterUnknownEnumList(
+ number,
+ enumList,
+ getEnumFieldVerifier(pos),
+ unknownFields,
+ unknownFieldSchema);
+ break;
+ }
+ case 31: // SFIXED32_LIST:
+ reader.readSFixed32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 32: // SFIXED64_LIST:
+ reader.readSFixed64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 33: // SINT32_LIST:
+ reader.readSInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 34: // SINT64_LIST:
+ reader.readSInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 35: // DOUBLE_LIST_PACKED:
+ reader.readDoubleList(
+ listFieldSchema.<Double>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 36: // FLOAT_LIST_PACKED:
+ reader.readFloatList(
+ listFieldSchema.<Float>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 37: // INT64_LIST_PACKED:
+ reader.readInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 38: // UINT64_LIST_PACKED:
+ reader.readUInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 39: // INT32_LIST_PACKED:
+ reader.readInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 40: // FIXED64_LIST_PACKED:
+ reader.readFixed64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 41: // FIXED32_LIST_PACKED:
+ reader.readFixed32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 42: // BOOL_LIST_PACKED:
+ reader.readBoolList(
+ listFieldSchema.<Boolean>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 43: // UINT32_LIST_PACKED:
+ reader.readUInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 44: // ENUM_LIST_PACKED:
+ {
+ List<Integer> enumList =
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset));
+ reader.readEnumList(enumList);
+ unknownFields =
+ SchemaUtil.filterUnknownEnumList(
+ number,
+ enumList,
+ getEnumFieldVerifier(pos),
+ unknownFields,
+ unknownFieldSchema);
+ break;
+ }
+ case 45: // SFIXED32_LIST_PACKED:
+ reader.readSFixed32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 46: // SFIXED64_LIST_PACKED:
+ reader.readSFixed64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 47: // SINT32_LIST_PACKED:
+ reader.readSInt32List(
+ listFieldSchema.<Integer>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 48: // SINT64_LIST_PACKED:
+ reader.readSInt64List(
+ listFieldSchema.<Long>mutableListAt(message, offset(typeAndOffset)));
+ break;
+ case 49:
+ { // GROUP_LIST:
+ readGroupList(
+ message,
+ offset(typeAndOffset),
+ reader,
+ (Schema<T>) getMessageFieldSchema(pos),
+ extensionRegistry);
+ break;
+ }
+ case 50: // MAP:
+ mergeMap(message, pos, getMapFieldDefaultEntry(pos), extensionRegistry, reader);
+ break;
+ case 51: // ONEOF_DOUBLE:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Double.valueOf(reader.readDouble()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 52: // ONEOF_FLOAT:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Float.valueOf(reader.readFloat()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 53: // ONEOF_INT64:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Long.valueOf(reader.readInt64()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 54: // ONEOF_UINT64:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Long.valueOf(reader.readUInt64()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 55: // ONEOF_INT32:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Integer.valueOf(reader.readInt32()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 56: // ONEOF_FIXED64:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Long.valueOf(reader.readFixed64()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 57: // ONEOF_FIXED32:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Integer.valueOf(reader.readFixed32()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 58: // ONEOF_BOOL:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Boolean.valueOf(reader.readBool()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 59: // ONEOF_STRING:
+ readString(message, typeAndOffset, reader);
+ setOneofPresent(message, number, pos);
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (isOneofPresent(message, number, pos)) {
+ Object mergedResult =
+ Internal.mergeMessage(
+ UnsafeUtil.getObject(message, offset(typeAndOffset)),
+ reader.readMessageBySchemaWithCheck(
+ getMessageFieldSchema(pos), extensionRegistry));
+ UnsafeUtil.putObject(message, offset(typeAndOffset), mergedResult);
+ } else {
+ UnsafeUtil.putObject(
+ message,
+ offset(typeAndOffset),
+ reader.readMessageBySchemaWithCheck(
+ getMessageFieldSchema(pos), extensionRegistry));
+ setFieldPresent(message, pos);
+ }
+ setOneofPresent(message, number, pos);
+ break;
+ case 61: // ONEOF_BYTES:
+ UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
+ setOneofPresent(message, number, pos);
+ break;
+ case 62: // ONEOF_UINT32:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Integer.valueOf(reader.readUInt32()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 63: // ONEOF_ENUM:
+ {
+ int enumValue = reader.readEnum();
+ EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
+ if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
+ UnsafeUtil.putObject(message, offset(typeAndOffset), enumValue);
+ setOneofPresent(message, number, pos);
+ } else {
+ unknownFields =
+ SchemaUtil.storeUnknownEnum(
+ number, enumValue, unknownFields, unknownFieldSchema);
+ }
+ break;
+ }
+ case 64: // ONEOF_SFIXED32:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Integer.valueOf(reader.readSFixed32()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 65: // ONEOF_SFIXED64:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Long.valueOf(reader.readSFixed64()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 66: // ONEOF_SINT32:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Integer.valueOf(reader.readSInt32()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 67: // ONEOF_SINT64:
+ UnsafeUtil.putObject(
+ message, offset(typeAndOffset), Long.valueOf(reader.readSInt64()));
+ setOneofPresent(message, number, pos);
+ break;
+ case 68: // ONEOF_GROUP:
+ UnsafeUtil.putObject(
+ message,
+ offset(typeAndOffset),
+ reader.readGroupBySchemaWithCheck(getMessageFieldSchema(pos), extensionRegistry));
+ setOneofPresent(message, number, pos);
+ break;
+ default:
+ // Assume we've landed on an empty entry. Treat it as an unknown field.
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.newBuilder();
+ }
+ if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
+ return;
+ }
+ break;
+ }
+ } catch (InvalidProtocolBufferException.InvalidWireTypeException e) {
+ // Treat fields with an invalid wire type as unknown fields
+ // (i.e. same as the default case).
+ if (unknownFieldSchema.shouldDiscardUnknownFields(reader)) {
+ if (!reader.skipField()) {
+ return;
+ }
+ } else {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ }
+ if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
+ return;
+ }
+ }
+ }
+ }
+ } finally {
+ for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
+ unknownFields =
+ filterMapUnknownEnumValues(message, intArray[i], unknownFields, unknownFieldSchema);
+ }
+ if (unknownFields != null) {
+ unknownFieldSchema.setBuilderToMessage(message, unknownFields);
+ }
+ }
+ }
+
+ @SuppressWarnings("ReferenceEquality")
+ static UnknownFieldSetLite getMutableUnknownFields(Object message) {
+ UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ ((GeneratedMessageLite) message).unknownFields = unknownFields;
+ }
+ return unknownFields;
+ }
+
+ /** Decodes a map entry key or value. Stores result in registers.object1. */
+ private int decodeMapEntryValue(
+ byte[] data,
+ int position,
+ int limit,
+ WireFormat.FieldType fieldType,
+ Class<?> messageType,
+ Registers registers)
+ throws IOException {
+ switch (fieldType) {
+ case BOOL:
+ position = decodeVarint64(data, position, registers);
+ registers.object1 = registers.long1 != 0;
+ break;
+ case BYTES:
+ position = decodeBytes(data, position, registers);
+ break;
+ case DOUBLE:
+ registers.object1 = decodeDouble(data, position);
+ position += 8;
+ break;
+ case FIXED32:
+ case SFIXED32:
+ registers.object1 = decodeFixed32(data, position);
+ position += 4;
+ break;
+ case FIXED64:
+ case SFIXED64:
+ registers.object1 = decodeFixed64(data, position);
+ position += 8;
+ break;
+ case FLOAT:
+ registers.object1 = decodeFloat(data, position);
+ position += 4;
+ break;
+ case ENUM:
+ case INT32:
+ case UINT32:
+ position = decodeVarint32(data, position, registers);
+ registers.object1 = registers.int1;
+ break;
+ case INT64:
+ case UINT64:
+ position = decodeVarint64(data, position, registers);
+ registers.object1 = registers.long1;
+ break;
+ case MESSAGE:
+ position =
+ decodeMessageField(
+ Protobuf.getInstance().schemaFor(messageType), data, position, limit, registers);
+ break;
+ case SINT32:
+ position = decodeVarint32(data, position, registers);
+ registers.object1 = CodedInputStream.decodeZigZag32(registers.int1);
+ break;
+ case SINT64:
+ position = decodeVarint64(data, position, registers);
+ registers.object1 = CodedInputStream.decodeZigZag64(registers.long1);
+ break;
+ case STRING:
+ position = decodeStringRequireUtf8(data, position, registers);
+ break;
+ default:
+ throw new RuntimeException("unsupported field type.");
+ }
+ return position;
+ }
+
+ /** Decodes a map entry. */
+ private <K, V> int decodeMapEntry(
+ byte[] data,
+ int position,
+ int limit,
+ MapEntryLite.Metadata<K, V> metadata,
+ Map<K, V> target,
+ Registers registers)
+ throws IOException {
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length < 0 || length > limit - position) {
+ throw InvalidProtocolBufferException.truncatedMessage();
+ }
+ final int end = position + length;
+ K key = metadata.defaultKey;
+ V value = metadata.defaultValue;
+ while (position < end) {
+ int tag = data[position++];
+ if (tag < 0) {
+ position = decodeVarint32(tag, data, position, registers);
+ tag = registers.int1;
+ }
+ final int fieldNumber = tag >>> 3;
+ final int wireType = tag & 0x7;
+ switch (fieldNumber) {
+ case 1:
+ if (wireType == metadata.keyType.getWireType()) {
+ position =
+ decodeMapEntryValue(data, position, limit, metadata.keyType, null, registers);
+ key = (K) registers.object1;
+ continue;
+ }
+ break;
+ case 2:
+ if (wireType == metadata.valueType.getWireType()) {
+ position =
+ decodeMapEntryValue(
+ data,
+ position,
+ limit,
+ metadata.valueType,
+ metadata.defaultValue.getClass(),
+ registers);
+ value = (V) registers.object1;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ position = skipField(tag, data, position, limit, registers);
+ }
+ if (position != end) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ target.put(key, value);
+ return end;
+ }
+
+ @SuppressWarnings("ReferenceEquality")
+ private int parseRepeatedField(
+ T message,
+ byte[] data,
+ int position,
+ int limit,
+ int tag,
+ int number,
+ int wireType,
+ int bufferPosition,
+ long typeAndOffset,
+ int fieldType,
+ long fieldOffset,
+ Registers registers)
+ throws IOException {
+ ProtobufList<?> list = (ProtobufList<?>) UNSAFE.getObject(message, fieldOffset);
+ if (!list.isModifiable()) {
+ final int size = list.size();
+ list =
+ list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ UNSAFE.putObject(message, fieldOffset, list);
+ }
+ switch (fieldType) {
+ case 18: // DOUBLE_LIST:
+ case 35: // DOUBLE_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedDoubleList(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ position = decodeDoubleList(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 19: // FLOAT_LIST:
+ case 36: // FLOAT_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedFloatList(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ position = decodeFloatList(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 20: // INT64_LIST:
+ case 21: // UINT64_LIST:
+ case 37: // INT64_LIST_PACKED:
+ case 38: // UINT64_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedVarint64List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 22: // INT32_LIST:
+ case 29: // UINT32_LIST:
+ case 39: // INT32_LIST_PACKED:
+ case 43: // UINT32_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedVarint32List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 23: // FIXED64_LIST:
+ case 32: // SFIXED64_LIST:
+ case 40: // FIXED64_LIST_PACKED:
+ case 46: // SFIXED64_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedFixed64List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ position = decodeFixed64List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 24: // FIXED32_LIST:
+ case 31: // SFIXED32_LIST:
+ case 41: // FIXED32_LIST_PACKED:
+ case 45: // SFIXED32_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedFixed32List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ position = decodeFixed32List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 25: // BOOL_LIST:
+ case 42: // BOOL_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedBoolList(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeBoolList(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 26: // STRING_LIST:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
+ position = decodeStringList(tag, data, position, limit, list, registers);
+ } else {
+ position = decodeStringListRequireUtf8(tag, data, position, limit, list, registers);
+ }
+ }
+ break;
+ case 27: // MESSAGE_LIST:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position =
+ decodeMessageList(
+ getMessageFieldSchema(bufferPosition),
+ tag,
+ data,
+ position,
+ limit,
+ list,
+ registers);
+ }
+ break;
+ case 28: // BYTES_LIST:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodeBytesList(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 30: // ENUM_LIST:
+ case 44: // ENUM_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedVarint32List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32List(tag, data, position, limit, list, registers);
+ } else {
+ break;
+ }
+ UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ // filterUnknownEnumList() expects the unknownFields parameter to be mutable or null.
+ // Since we don't know yet whether there exist unknown enum values, we'd better pass
+ // null to it instead of allocating a mutable instance. This is also needed to be
+ // consistent with the behavior of generated parser/builder.
+ unknownFields = null;
+ }
+ unknownFields =
+ SchemaUtil.filterUnknownEnumList(
+ number,
+ (ProtobufList<Integer>) list,
+ getEnumFieldVerifier(bufferPosition),
+ unknownFields,
+ (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema);
+ if (unknownFields != null) {
+ ((GeneratedMessageLite) message).unknownFields = unknownFields;
+ }
+ break;
+ case 33: // SINT32_LIST:
+ case 47: // SINT32_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedSInt32List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeSInt32List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 34: // SINT64_LIST:
+ case 48: // SINT64_LIST_PACKED:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodePackedSInt64List(data, position, list, registers);
+ } else if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeSInt64List(tag, data, position, limit, list, registers);
+ }
+ break;
+ case 49: // GROUP_LIST:
+ if (wireType == WireFormat.WIRETYPE_START_GROUP) {
+ position =
+ decodeGroupList(
+ getMessageFieldSchema(bufferPosition),
+ tag,
+ data,
+ position,
+ limit,
+ list,
+ registers);
+ }
+ break;
+ default:
+ break;
+ }
+ return position;
+ }
+
+ private <K, V> int parseMapField(
+ T message,
+ byte[] data,
+ int position,
+ int limit,
+ int bufferPosition,
+ long fieldOffset,
+ Registers registers)
+ throws IOException {
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ Object mapDefaultEntry = getMapFieldDefaultEntry(bufferPosition);
+ Object mapField = unsafe.getObject(message, fieldOffset);
+ if (mapFieldSchema.isImmutable(mapField)) {
+ Object oldMapField = mapField;
+ mapField = mapFieldSchema.newMapField(mapDefaultEntry);
+ mapFieldSchema.mergeFrom(mapField, oldMapField);
+ unsafe.putObject(message, fieldOffset, mapField);
+ }
+ return decodeMapEntry(
+ data,
+ position,
+ limit,
+ (Metadata<K, V>) mapFieldSchema.forMapMetadata(mapDefaultEntry),
+ (Map<K, V>) mapFieldSchema.forMutableMapData(mapField),
+ registers);
+ }
+
+ private int parseOneofField(
+ T message,
+ byte[] data,
+ int position,
+ int limit,
+ int tag,
+ int number,
+ int wireType,
+ int typeAndOffset,
+ int fieldType,
+ long fieldOffset,
+ int bufferPosition,
+ Registers registers)
+ throws IOException {
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ final long oneofCaseOffset = buffer[bufferPosition + 2] & OFFSET_MASK;
+ switch (fieldType) {
+ case 51: // ONEOF_DOUBLE:
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ unsafe.putObject(message, fieldOffset, decodeDouble(data, position));
+ position += 8;
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 52: // ONEOF_FLOAT:
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ unsafe.putObject(message, fieldOffset, decodeFloat(data, position));
+ position += 4;
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 53: // ONEOF_INT64:
+ case 54: // ONEOF_UINT64:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.long1);
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 55: // ONEOF_INT32:
+ case 62: // ONEOF_UINT32:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.int1);
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 56: // ONEOF_FIXED64:
+ case 65: // ONEOF_SFIXED64:
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ unsafe.putObject(message, fieldOffset, decodeFixed64(data, position));
+ position += 8;
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 57: // ONEOF_FIXED32:
+ case 64: // ONEOF_SFIXED32:
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ unsafe.putObject(message, fieldOffset, decodeFixed32(data, position));
+ position += 4;
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 58: // ONEOF_BOOL:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.long1 != 0);
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 59: // ONEOF_STRING:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodeVarint32(data, position, registers);
+ final int length = registers.int1;
+ if (length == 0) {
+ unsafe.putObject(message, fieldOffset, "");
+ } else {
+ if ((typeAndOffset & ENFORCE_UTF8_MASK) != 0
+ && !Utf8.isValidUtf8(data, position, position + length)) {
+ throw InvalidProtocolBufferException.invalidUtf8();
+ }
+ final String value = new String(data, position, length, Internal.UTF_8);
+ unsafe.putObject(message, fieldOffset, value);
+ position += length;
+ }
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 60: // ONEOF_MESSAGE:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position =
+ decodeMessageField(
+ getMessageFieldSchema(bufferPosition), data, position, limit, registers);
+ final Object oldValue =
+ unsafe.getInt(message, oneofCaseOffset) == number
+ ? unsafe.getObject(message, fieldOffset)
+ : null;
+ if (oldValue == null) {
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ } else {
+ unsafe.putObject(
+ message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
+ }
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 61: // ONEOF_BYTES:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodeBytes(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 63: // ONEOF_ENUM:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ final int enumValue = registers.int1;
+ EnumVerifier enumVerifier = getEnumFieldVerifier(bufferPosition);
+ if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
+ unsafe.putObject(message, fieldOffset, enumValue);
+ unsafe.putInt(message, oneofCaseOffset, number);
+ } else {
+ // UnknownFieldSetLite requires varint to be represented as Long:
+ // https://cs.corp.google.com/piper///depot/google3/java/com/google/protobuf/UnknownFieldSetLite.java?l=202&rcl=167074986
+ getMutableUnknownFields(message).storeField(tag, (long) enumValue);
+ }
+ }
+ break;
+ case 66: // ONEOF_SINT32:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 67: // ONEOF_SINT64:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putObject(message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ case 68: // ONEOF_GROUP:
+ if (wireType == WireFormat.WIRETYPE_START_GROUP) {
+ final int endTag = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP;
+ position =
+ decodeGroupField(
+ getMessageFieldSchema(bufferPosition), data, position, limit, endTag, registers);
+ final Object oldValue =
+ unsafe.getInt(message, oneofCaseOffset) == number
+ ? unsafe.getObject(message, fieldOffset)
+ : null;
+ if (oldValue == null) {
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ } else {
+ unsafe.putObject(
+ message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
+ }
+ unsafe.putInt(message, oneofCaseOffset, number);
+ }
+ break;
+ default:
+ break;
+ }
+ return position;
+ }
+
+ private Schema getMessageFieldSchema(int pos) {
+ final int index = pos / INTS_PER_FIELD * 2;
+ Schema schema = (Schema) objects[index];
+ if (schema != null) {
+ return schema;
+ }
+ schema = Protobuf.getInstance().schemaFor((Class) objects[index + 1]);
+ objects[index] = schema;
+ return schema;
+ }
+
+ private Object getMapFieldDefaultEntry(int pos) {
+ return objects[pos / INTS_PER_FIELD * 2];
+ }
+
+ private EnumVerifier getEnumFieldVerifier(int pos) {
+ return (EnumVerifier) objects[pos / INTS_PER_FIELD * 2 + 1];
+ }
+
+ /**
+ * Parses a proto2 message or group and returns the position after the message/group. If it's
+ * parsing a message (endGroup == 0), returns limit if parsing is successful; It it's parsing a
+ * group (endGroup != 0), parsing ends when a tag == endGroup is encountered and the position
+ * after that tag is returned.
+ */
+ int parseProto2Message(
+ T message, byte[] data, int position, int limit, int endGroup, Registers registers)
+ throws IOException {
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ int currentPresenceFieldOffset = -1;
+ int currentPresenceField = 0;
+ int tag = 0;
+ int oldNumber = -1;
+ int pos = 0;
+ while (position < limit) {
+ tag = data[position++];
+ if (tag < 0) {
+ position = decodeVarint32(tag, data, position, registers);
+ tag = registers.int1;
+ }
+ final int number = tag >>> 3;
+ final int wireType = tag & 0x7;
+ if (number > oldNumber) {
+ pos = positionForFieldNumber(number, pos / INTS_PER_FIELD);
+ } else {
+ pos = positionForFieldNumber(number);
+ }
+ oldNumber = number;
+ if (pos == -1) {
+ // need to reset
+ pos = 0;
+ } else {
+ final int typeAndOffset = buffer[pos + 1];
+ final int fieldType = type(typeAndOffset);
+ final long fieldOffset = offset(typeAndOffset);
+ if (fieldType <= 17) {
+ // Proto2 optional fields have has-bits.
+ final int presenceMaskAndOffset = buffer[pos + 2];
+ final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
+ // We cache the 32-bit has-bits integer value and only write it back when parsing a field
+ // using a different has-bits integer.
+ if (presenceFieldOffset != currentPresenceFieldOffset) {
+ if (currentPresenceFieldOffset != -1) {
+ unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
+ }
+ currentPresenceFieldOffset = presenceFieldOffset;
+ currentPresenceField = unsafe.getInt(message, (long) presenceFieldOffset);
+ }
+ switch (fieldType) {
+ case 0: // DOUBLE
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position));
+ position += 8;
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 1: // FLOAT
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position));
+ position += 4;
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 2: // INT64
+ case 3: // UINT64
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putLong(message, fieldOffset, registers.long1);
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 4: // INT32
+ case 11: // UINT32
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putInt(message, fieldOffset, registers.int1);
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 5: // FIXED64
+ case 14: // SFIXED64
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ unsafe.putLong(message, fieldOffset, decodeFixed64(data, position));
+ position += 8;
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 6: // FIXED32
+ case 13: // SFIXED32
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ unsafe.putInt(message, fieldOffset, decodeFixed32(data, position));
+ position += 4;
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 7: // BOOL
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0);
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 8: // STRING
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
+ position = decodeString(data, position, registers);
+ } else {
+ position = decodeStringRequireUtf8(data, position, registers);
+ }
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 9: // MESSAGE
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position =
+ decodeMessageField(
+ getMessageFieldSchema(pos), data, position, limit, registers);
+ if ((currentPresenceField & presenceMask) == 0) {
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ } else {
+ unsafe.putObject(
+ message,
+ fieldOffset,
+ Internal.mergeMessage(
+ unsafe.getObject(message, fieldOffset), registers.object1));
+ }
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 10: // BYTES
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodeBytes(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 12: // ENUM
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ final int enumValue = registers.int1;
+ EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
+ if (enumVerifier == null || enumVerifier.isInRange(enumValue)) {
+ unsafe.putInt(message, fieldOffset, enumValue);
+ currentPresenceField |= presenceMask;
+ } else {
+ // UnknownFieldSetLite requires varint to be represented as Long:
+ // https://cs.corp.google.com/piper///depot/google3/java/com/google/protobuf/UnknownFieldSetLite.java?l=202&rcl=167074986
+ getMutableUnknownFields(message).storeField(tag, (long) enumValue);
+ }
+ continue;
+ }
+ break;
+ case 15: // SINT32
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putInt(
+ message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 16: // SINT64
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putLong(
+ message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
+
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ case 17: // GROUP
+ if (wireType == WireFormat.WIRETYPE_START_GROUP) {
+ final int endTag = (number << 3) | WireFormat.WIRETYPE_END_GROUP;
+ position =
+ decodeGroupField(
+ getMessageFieldSchema(pos), data, position, limit, endTag, registers);
+ if ((currentPresenceField & presenceMask) == 0) {
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ } else {
+ unsafe.putObject(
+ message,
+ fieldOffset,
+ Internal.mergeMessage(
+ unsafe.getObject(message, fieldOffset), registers.object1));
+ }
+
+ currentPresenceField |= presenceMask;
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (fieldType == 27) {
+ // Handle repeated message fields.
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ ProtobufList<?> list = (ProtobufList<?>) unsafe.getObject(message, fieldOffset);
+ if (!list.isModifiable()) {
+ final int size = list.size();
+ list =
+ list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ unsafe.putObject(message, fieldOffset, list);
+ }
+ position =
+ decodeMessageList(
+ getMessageFieldSchema(pos), tag, data, position, limit, list, registers);
+ continue;
+ }
+ } else if (fieldType <= 49) {
+ // Handle all other repeated fields.
+ final int oldPosition = position;
+ position =
+ parseRepeatedField(
+ message,
+ data,
+ position,
+ limit,
+ tag,
+ number,
+ wireType,
+ pos,
+ typeAndOffset,
+ fieldType,
+ fieldOffset,
+ registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ } else if (fieldType == 50) {
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ final int oldPosition = position;
+ position = parseMapField(message, data, position, limit, pos, fieldOffset, registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ }
+ } else {
+ final int oldPosition = position;
+ position =
+ parseOneofField(
+ message,
+ data,
+ position,
+ limit,
+ tag,
+ number,
+ wireType,
+ typeAndOffset,
+ fieldType,
+ fieldOffset,
+ pos,
+ registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ }
+ }
+ if (tag == endGroup && endGroup != 0) {
+ break;
+ }
+
+ if (hasExtensions
+ && registers.extensionRegistry != ExtensionRegistryLite.getEmptyRegistry()) {
+ position = decodeExtensionOrUnknownField(
+ tag, data, position, limit, message, defaultInstance,
+ (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema,
+ registers);
+ } else {
+ position = decodeUnknownField(
+ tag, data, position, limit, getMutableUnknownFields(message), registers);
+ }
+ }
+ if (currentPresenceFieldOffset != -1) {
+ unsafe.putInt(message, (long) currentPresenceFieldOffset, currentPresenceField);
+ }
+ UnknownFieldSetLite unknownFields = null;
+ for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
+ unknownFields =
+ filterMapUnknownEnumValues(
+ message,
+ intArray[i],
+ unknownFields,
+ (UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema);
+ }
+ if (unknownFields != null) {
+ ((UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite>) unknownFieldSchema)
+ .setBuilderToMessage(message, unknownFields);
+ }
+ if (endGroup == 0) {
+ if (position != limit) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ } else {
+ if (position > limit || tag != endGroup) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+ return position;
+ }
+
+ /** Parses a proto3 message and returns the limit if parsing is successful. */
+ private int parseProto3Message(
+ T message, byte[] data, int position, int limit, Registers registers) throws IOException {
+ final sun.misc.Unsafe unsafe = UNSAFE;
+ int tag = 0;
+ int oldNumber = -1;
+ int pos = 0;
+ while (position < limit) {
+ tag = data[position++];
+ if (tag < 0) {
+ position = decodeVarint32(tag, data, position, registers);
+ tag = registers.int1;
+ }
+ final int number = tag >>> 3;
+ final int wireType = tag & 0x7;
+ if (number > oldNumber) {
+ pos = positionForFieldNumber(number, pos / INTS_PER_FIELD);
+ } else {
+ pos = positionForFieldNumber(number);
+ }
+ oldNumber = number;
+ if (pos == -1) {
+ // need to reset
+ pos = 0;
+ } else {
+ final int typeAndOffset = buffer[pos + 1];
+ final int fieldType = type(typeAndOffset);
+ final long fieldOffset = offset(typeAndOffset);
+ if (fieldType <= 17) {
+ switch (fieldType) {
+ case 0: // DOUBLE:
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ UnsafeUtil.putDouble(message, fieldOffset, decodeDouble(data, position));
+ position += 8;
+ continue;
+ }
+ break;
+ case 1: // FLOAT:
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ UnsafeUtil.putFloat(message, fieldOffset, decodeFloat(data, position));
+ position += 4;
+ continue;
+ }
+ break;
+ case 2: // INT64:
+ case 3: // UINT64:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putLong(message, fieldOffset, registers.long1);
+ continue;
+ }
+ break;
+ case 4: // INT32:
+ case 11: // UINT32:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putInt(message, fieldOffset, registers.int1);
+ continue;
+ }
+ break;
+ case 5: // FIXED64:
+ case 14: // SFIXED64:
+ if (wireType == WireFormat.WIRETYPE_FIXED64) {
+ unsafe.putLong(message, fieldOffset, decodeFixed64(data, position));
+ position += 8;
+ continue;
+ }
+ break;
+ case 6: // FIXED32:
+ case 13: // SFIXED32:
+ if (wireType == WireFormat.WIRETYPE_FIXED32) {
+ unsafe.putInt(message, fieldOffset, decodeFixed32(data, position));
+ position += 4;
+ continue;
+ }
+ break;
+ case 7: // BOOL:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ UnsafeUtil.putBoolean(message, fieldOffset, registers.long1 != 0);
+ continue;
+ }
+ break;
+ case 8: // STRING:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ if ((typeAndOffset & ENFORCE_UTF8_MASK) == 0) {
+ position = decodeString(data, position, registers);
+ } else {
+ position = decodeStringRequireUtf8(data, position, registers);
+ }
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ continue;
+ }
+ break;
+ case 9: // MESSAGE:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position =
+ decodeMessageField(
+ getMessageFieldSchema(pos), data, position, limit, registers);
+ final Object oldValue = unsafe.getObject(message, fieldOffset);
+ if (oldValue == null) {
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ } else {
+ unsafe.putObject(
+ message, fieldOffset, Internal.mergeMessage(oldValue, registers.object1));
+ }
+ continue;
+ }
+ break;
+ case 10: // BYTES:
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = decodeBytes(data, position, registers);
+ unsafe.putObject(message, fieldOffset, registers.object1);
+ continue;
+ }
+ break;
+ case 12: // ENUM:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putInt(message, fieldOffset, registers.int1);
+ continue;
+ }
+ break;
+ case 15: // SINT32:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint32(data, position, registers);
+ unsafe.putInt(
+ message, fieldOffset, CodedInputStream.decodeZigZag32(registers.int1));
+ continue;
+ }
+ break;
+ case 16: // SINT64:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = decodeVarint64(data, position, registers);
+ unsafe.putLong(
+ message, fieldOffset, CodedInputStream.decodeZigZag64(registers.long1));
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (fieldType == 27) {
+ // Handle repeated message field.
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ ProtobufList<?> list = (ProtobufList<?>) unsafe.getObject(message, fieldOffset);
+ if (!list.isModifiable()) {
+ final int size = list.size();
+ list =
+ list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ unsafe.putObject(message, fieldOffset, list);
+ }
+ position =
+ decodeMessageList(
+ getMessageFieldSchema(pos), tag, data, position, limit, list, registers);
+ continue;
+ }
+ } else if (fieldType <= 49) {
+ // Handle all other repeated fields.
+ final int oldPosition = position;
+ position =
+ parseRepeatedField(
+ message,
+ data,
+ position,
+ limit,
+ tag,
+ number,
+ wireType,
+ pos,
+ typeAndOffset,
+ fieldType,
+ fieldOffset,
+ registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ } else if (fieldType == 50) {
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ final int oldPosition = position;
+ position = parseMapField(message, data, position, limit, pos, fieldOffset, registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ }
+ } else {
+ final int oldPosition = position;
+ position =
+ parseOneofField(
+ message,
+ data,
+ position,
+ limit,
+ tag,
+ number,
+ wireType,
+ typeAndOffset,
+ fieldType,
+ fieldOffset,
+ pos,
+ registers);
+ if (position != oldPosition) {
+ continue;
+ }
+ }
+ }
+ position = decodeUnknownField(
+ tag, data, position, limit, getMutableUnknownFields(message), registers);
+ }
+ if (position != limit) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ return position;
+ }
+
+ @Override
+ public void mergeFrom(T message, byte[] data, int position, int limit, Registers registers)
+ throws IOException {
+ if (proto3) {
+ parseProto3Message(message, data, position, limit, registers);
+ } else {
+ parseProto2Message(message, data, position, limit, 0, registers);
+ }
+ }
+
+ @Override
+ public void makeImmutable(T message) {
+ // Make all repeated/map fields immutable.
+ for (int i = checkInitializedCount; i < repeatedFieldOffsetStart; i++) {
+ long offset = offset(typeAndOffsetAt(intArray[i]));
+ Object mapField = UnsafeUtil.getObject(message, offset);
+ if (mapField == null) {
+ continue;
+ }
+ UnsafeUtil.putObject(message, offset, mapFieldSchema.toImmutable(mapField));
+ }
+ final int length = intArray.length;
+ for (int i = repeatedFieldOffsetStart; i < length; i++) {
+ listFieldSchema.makeImmutableListAt(message, intArray[i]);
+ }
+ unknownFieldSchema.makeImmutable(message);
+ if (hasExtensions) {
+ extensionSchema.makeImmutable(message);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private final <K, V> void mergeMap(
+ Object message,
+ int pos,
+ Object mapDefaultEntry,
+ ExtensionRegistryLite extensionRegistry,
+ Reader reader)
+ throws IOException {
+ long offset = offset(typeAndOffsetAt(pos));
+ Object mapField = UnsafeUtil.getObject(message, offset);
+ // TODO(xiaofeng): Consider creating separate implementations for full and lite. In lite
+ // runtime map field will never be null but here we still need to check null because the
+ // code is shared by both full and lite. It might be better if full/lite uses different
+ // schema implementations.
+ if (mapField == null) {
+ mapField = mapFieldSchema.newMapField(mapDefaultEntry);
+ UnsafeUtil.putObject(message, offset, mapField);
+ } else if (mapFieldSchema.isImmutable(mapField)) {
+ Object oldMapField = mapField;
+ mapField = mapFieldSchema.newMapField(mapDefaultEntry);
+ mapFieldSchema.mergeFrom(mapField, oldMapField);
+ UnsafeUtil.putObject(message, offset, mapField);
+ }
+ reader.readMap(
+ (Map<K, V>) mapFieldSchema.forMutableMapData(mapField),
+ (Metadata<K, V>) mapFieldSchema.forMapMetadata(mapDefaultEntry),
+ extensionRegistry);
+ }
+
+ private final <UT, UB> UB filterMapUnknownEnumValues(
+ Object message, int pos, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema) {
+ int fieldNumber = numberAt(pos);
+ long offset = offset(typeAndOffsetAt(pos));
+ Object mapField = UnsafeUtil.getObject(message, offset);
+ if (mapField == null) {
+ return unknownFields;
+ }
+ EnumVerifier enumVerifier = getEnumFieldVerifier(pos);
+ if (enumVerifier == null) {
+ return unknownFields;
+ }
+ Map<?, ?> mapData = mapFieldSchema.forMutableMapData(mapField);
+ // Filter unknown enum values.
+ unknownFields =
+ filterUnknownEnumMap(
+ pos, fieldNumber, mapData, enumVerifier, unknownFields, unknownFieldSchema);
+ return unknownFields;
+ }
+
+ @SuppressWarnings("unchecked")
+ private final <K, V, UT, UB> UB filterUnknownEnumMap(
+ int pos,
+ int number,
+ Map<K, V> mapData,
+ EnumVerifier enumVerifier,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema) {
+ Metadata<K, V> metadata =
+ (Metadata<K, V>) mapFieldSchema.forMapMetadata(getMapFieldDefaultEntry(pos));
+ for (Iterator<Map.Entry<K, V>> it = mapData.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry<K, V> entry = it.next();
+ if (!enumVerifier.isInRange((Integer) entry.getValue())) {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.newBuilder();
+ }
+ int entrySize =
+ MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue());
+ CodedBuilder codedBuilder = ByteString.newCodedBuilder(entrySize);
+ CodedOutputStream codedOutput = codedBuilder.getCodedOutput();
+ try {
+ MapEntryLite.writeTo(codedOutput, metadata, entry.getKey(), entry.getValue());
+ } catch (IOException e) {
+ // Writing to ByteString CodedOutputStream should not throw IOException.
+ throw new RuntimeException(e);
+ }
+ unknownFieldSchema.addLengthDelimited(unknownFields, number, codedBuilder.build());
+ it.remove();
+ }
+ }
+ return unknownFields;
+ }
+
+ @Override
+ public final boolean isInitialized(T message) {
+ int currentPresenceFieldOffset = -1;
+ int currentPresenceField = 0;
+ for (int i = 0; i < checkInitializedCount; i++) {
+ final int pos = intArray[i];
+ final int number = numberAt(pos);
+
+ final int typeAndOffset = typeAndOffsetAt(pos);
+
+ int presenceMaskAndOffset = 0;
+ int presenceMask = 0;
+ if (!proto3) {
+ presenceMaskAndOffset = buffer[pos + 2];
+ final int presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
+ presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ if (presenceFieldOffset != currentPresenceFieldOffset) {
+ currentPresenceFieldOffset = presenceFieldOffset;
+ currentPresenceField = UNSAFE.getInt(message, (long) presenceFieldOffset);
+ }
+ }
+
+ if (isRequired(typeAndOffset)) {
+ if (!isFieldPresent(message, pos, currentPresenceField, presenceMask)) {
+ return false;
+ }
+ // If a required message field is set but has no required fields of it's own, we still
+ // proceed and check the message is initialized. It should be fairly cheap to check these
+ // messages but is worth documenting.
+ }
+ // Check nested message and groups.
+ switch (type(typeAndOffset)) {
+ case 9: // MESSAGE
+ case 17: // GROUP
+ if (isFieldPresent(message, pos, currentPresenceField, presenceMask)
+ && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) {
+ return false;
+ }
+ break;
+ case 27: // MESSAGE_LIST
+ case 49: // GROUP_LIST
+ if (!isListInitialized(message, typeAndOffset, pos)) {
+ return false;
+ }
+ break;
+ case 60: // ONEOF_MESSAGE
+ case 68: // ONEOF_GROUP
+ if (isOneofPresent(message, number, pos)
+ && !isInitialized(message, typeAndOffset, getMessageFieldSchema(pos))) {
+ return false;
+ }
+ break;
+ case 50: // MAP
+ if (!isMapInitialized(message, typeAndOffset, pos)) {
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (hasExtensions) {
+ if (!extensionSchema.getExtensions(message).isInitialized()) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static boolean isInitialized(Object message, int typeAndOffset, Schema schema) {
+ Object nested = UnsafeUtil.getObject(message, offset(typeAndOffset));
+ return schema.isInitialized(nested);
+ }
+
+ private <N> boolean isListInitialized(Object message, int typeAndOffset, int pos) {
+ @SuppressWarnings("unchecked")
+ List<N> list = (List<N>) UnsafeUtil.getObject(message, offset(typeAndOffset));
+ if (list.isEmpty()) {
+ return true;
+ }
+
+ Schema schema = getMessageFieldSchema(pos);
+ for (int i = 0; i < list.size(); i++) {
+ N nested = list.get(i);
+ if (!schema.isInitialized(nested)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isMapInitialized(T message, int typeAndOffset, int pos) {
+ Map<?, ?> map = mapFieldSchema.forMapData(UnsafeUtil.getObject(message, offset(typeAndOffset)));
+ if (map.isEmpty()) {
+ return true;
+ }
+ Object mapDefaultEntry = getMapFieldDefaultEntry(pos);
+ MapEntryLite.Metadata<?, ?> metadata = mapFieldSchema.forMapMetadata(mapDefaultEntry);
+ if (metadata.valueType.getJavaType() != WireFormat.JavaType.MESSAGE) {
+ return true;
+ }
+ // TODO(dweis): Use schema cache.
+ Schema schema = null;
+ for (Object nested : map.values()) {
+ if (schema == null) {
+ schema = Protobuf.getInstance().schemaFor(nested.getClass());
+ }
+ if (!schema.isInitialized(nested)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
+ if (value instanceof String) {
+ writer.writeString(fieldNumber, (String) value);
+ } else {
+ writer.writeBytes(fieldNumber, (ByteString) value);
+ }
+ }
+
+ private void readString(Object message, int typeAndOffset, Reader reader) throws IOException {
+ if (isEnforceUtf8(typeAndOffset)) {
+ // Enforce valid UTF-8 on the read.
+ UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readStringRequireUtf8());
+ } else if (lite) {
+ // Lite messages use String fields to store strings. Read a string but do not
+ // enforce UTF-8
+ UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readString());
+ } else {
+ // Full runtime messages use Objects to store either a String or ByteString. Read
+ // the string as a ByteString and do not enforce UTF-8.
+ UnsafeUtil.putObject(message, offset(typeAndOffset), reader.readBytes());
+ }
+ }
+
+ private void readStringList(Object message, int typeAndOffset, Reader reader) throws IOException {
+ if (isEnforceUtf8(typeAndOffset)) {
+ reader.readStringListRequireUtf8(
+ listFieldSchema.<String>mutableListAt(message, offset(typeAndOffset)));
+ } else {
+ reader.readStringList(listFieldSchema.<String>mutableListAt(message, offset(typeAndOffset)));
+ }
+ }
+
+ private <E> void readMessageList(
+ Object message,
+ int typeAndOffset,
+ Reader reader,
+ Schema<E> schema,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ long offset = offset(typeAndOffset);
+ reader.readMessageList(
+ listFieldSchema.<E>mutableListAt(message, offset), schema, extensionRegistry);
+ }
+
+ private <E> void readGroupList(
+ Object message,
+ long offset,
+ Reader reader,
+ Schema<E> schema,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ reader.readGroupList(
+ listFieldSchema.<E>mutableListAt(message, offset), schema, extensionRegistry);
+ }
+
+ private int numberAt(int pos) {
+ return buffer[pos];
+ }
+
+ private int typeAndOffsetAt(int pos) {
+ return buffer[pos + 1];
+ }
+
+ private int presenceMaskAndOffsetAt(int pos) {
+ return buffer[pos + 2];
+ }
+
+ private static int type(int value) {
+ return (value & FIELD_TYPE_MASK) >>> OFFSET_BITS;
+ }
+
+ private static boolean isRequired(int value) {
+ return (value & REQUIRED_MASK) != 0;
+ }
+
+ private static boolean isEnforceUtf8(int value) {
+ return (value & ENFORCE_UTF8_MASK) != 0;
+ }
+
+ private static long offset(int value) {
+ return value & OFFSET_MASK;
+ }
+
+ private static <T> double doubleAt(T message, long offset) {
+ return UnsafeUtil.getDouble(message, offset);
+ }
+
+ private static <T> float floatAt(T message, long offset) {
+ return UnsafeUtil.getFloat(message, offset);
+ }
+
+ private static <T> int intAt(T message, long offset) {
+ return UnsafeUtil.getInt(message, offset);
+ }
+
+ private static <T> long longAt(T message, long offset) {
+ return UnsafeUtil.getLong(message, offset);
+ }
+
+ private static <T> boolean booleanAt(T message, long offset) {
+ return UnsafeUtil.getBoolean(message, offset);
+ }
+
+ private static <T> double oneofDoubleAt(T message, long offset) {
+ return ((Double) UnsafeUtil.getObject(message, offset)).doubleValue();
+ }
+
+ private static <T> float oneofFloatAt(T message, long offset) {
+ return ((Float) UnsafeUtil.getObject(message, offset)).floatValue();
+ }
+
+ private static <T> int oneofIntAt(T message, long offset) {
+ return ((Integer) UnsafeUtil.getObject(message, offset)).intValue();
+ }
+
+ private static <T> long oneofLongAt(T message, long offset) {
+ return ((Long) UnsafeUtil.getObject(message, offset)).longValue();
+ }
+
+ private static <T> boolean oneofBooleanAt(T message, long offset) {
+ return ((Boolean) UnsafeUtil.getObject(message, offset)).booleanValue();
+ }
+
+ /** Returns true the field is present in both messages, or neither. */
+ private boolean arePresentForEquals(T message, T other, int pos) {
+ return isFieldPresent(message, pos) == isFieldPresent(other, pos);
+ }
+
+ private boolean isFieldPresent(T message, int pos, int presenceField, int presenceMask) {
+ if (proto3) {
+ return isFieldPresent(message, pos);
+ } else {
+ return (presenceField & presenceMask) != 0;
+ }
+ }
+
+ private boolean isFieldPresent(T message, int pos) {
+ if (proto3) {
+ final int typeAndOffset = typeAndOffsetAt(pos);
+ final long offset = offset(typeAndOffset);
+ switch (type(typeAndOffset)) {
+ case 0: // DOUBLE:
+ return UnsafeUtil.getDouble(message, offset) != 0D;
+ case 1: // FLOAT:
+ return UnsafeUtil.getFloat(message, offset) != 0F;
+ case 2: // INT64:
+ return UnsafeUtil.getLong(message, offset) != 0L;
+ case 3: // UINT64:
+ return UnsafeUtil.getLong(message, offset) != 0L;
+ case 4: // INT32:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 5: // FIXED64:
+ return UnsafeUtil.getLong(message, offset) != 0L;
+ case 6: // FIXED32:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 7: // BOOL:
+ return UnsafeUtil.getBoolean(message, offset);
+ case 8: // STRING:
+ Object value = UnsafeUtil.getObject(message, offset);
+ if (value instanceof String) {
+ return !((String) value).isEmpty();
+ } else if (value instanceof ByteString) {
+ return !ByteString.EMPTY.equals(value);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ case 9: // MESSAGE:
+ return UnsafeUtil.getObject(message, offset) != null;
+ case 10: // BYTES:
+ return !ByteString.EMPTY.equals(UnsafeUtil.getObject(message, offset));
+ case 11: // UINT32:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 12: // ENUM:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 13: // SFIXED32:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 14: // SFIXED64:
+ return UnsafeUtil.getLong(message, offset) != 0L;
+ case 15: // SINT32:
+ return UnsafeUtil.getInt(message, offset) != 0;
+ case 16: // SINT64:
+ return UnsafeUtil.getLong(message, offset) != 0L;
+ case 17: // GROUP:
+ return UnsafeUtil.getObject(message, offset) != null;
+ default:
+ throw new IllegalArgumentException();
+ }
+ } else {
+ int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
+ final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ return (UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) & presenceMask) != 0;
+ }
+ }
+
+ private void setFieldPresent(T message, int pos) {
+ if (proto3) {
+ // Proto3 doesn't have presence fields
+ return;
+ }
+ int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
+ final int presenceMask = 1 << (presenceMaskAndOffset >>> OFFSET_BITS);
+ final long presenceFieldOffset = presenceMaskAndOffset & OFFSET_MASK;
+ UnsafeUtil.putInt(
+ message,
+ presenceFieldOffset,
+ UnsafeUtil.getInt(message, presenceFieldOffset) | presenceMask);
+ }
+
+ private boolean isOneofPresent(T message, int fieldNumber, int pos) {
+ int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
+ return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK) == fieldNumber;
+ }
+
+ private boolean isOneofCaseEqual(T message, T other, int pos) {
+ int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
+ return UnsafeUtil.getInt(message, presenceMaskAndOffset & OFFSET_MASK)
+ == UnsafeUtil.getInt(other, presenceMaskAndOffset & OFFSET_MASK);
+ }
+
+ private void setOneofPresent(T message, int fieldNumber, int pos) {
+ int presenceMaskAndOffset = presenceMaskAndOffsetAt(pos);
+ UnsafeUtil.putInt(message, presenceMaskAndOffset & OFFSET_MASK, fieldNumber);
+ }
+
+ private int positionForFieldNumber(final int number) {
+ if (number >= minFieldNumber && number <= maxFieldNumber) {
+ return slowPositionForFieldNumber(number, 0);
+ }
+ return -1;
+ }
+
+ private int positionForFieldNumber(final int number, final int min) {
+ if (number >= minFieldNumber && number <= maxFieldNumber) {
+ return slowPositionForFieldNumber(number, min);
+ }
+ return -1;
+ }
+
+ private int slowPositionForFieldNumber(final int number, int min) {
+ int max = buffer.length / INTS_PER_FIELD - 1;
+ while (min <= max) {
+ // Find the midpoint address.
+ final int mid = (max + min) >>> 1;
+ final int pos = mid * INTS_PER_FIELD;
+ final int midFieldNumber = numberAt(pos);
+ if (number == midFieldNumber) {
+ // Found the field.
+ return pos;
+ }
+ if (number < midFieldNumber) {
+ // Search the lower half.
+ max = mid - 1;
+ } else {
+ // Search the upper half.
+ min = mid + 1;
+ }
+ }
+ return -1;
+ }
+
+ int getSchemaSize() {
+ return buffer.length * 3;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
new file mode 100755
index 000000000..187dc8b8a
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
@@ -0,0 +1,392 @@
+// 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.Iterator;
+import java.util.Map.Entry;
+
+/** Schema used for proto2 messages using message_set_wireformat. */
+final class MessageSetSchema<T> implements Schema<T> {
+ private final MessageLite defaultInstance;
+ private final UnknownFieldSchema<?, ?> unknownFieldSchema;
+ private final boolean hasExtensions;
+ private final ExtensionSchema<?> extensionSchema;
+
+ private MessageSetSchema(
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MessageLite defaultInstance) {
+ this.unknownFieldSchema = unknownFieldSchema;
+ this.hasExtensions = extensionSchema.hasExtensions(defaultInstance);
+ this.extensionSchema = extensionSchema;
+ this.defaultInstance = defaultInstance;
+ }
+
+ static <T> MessageSetSchema<T> newSchema(
+ UnknownFieldSchema<?, ?> unknownFieldSchema,
+ ExtensionSchema<?> extensionSchema,
+ MessageLite defaultInstance) {
+ return new MessageSetSchema<T>(unknownFieldSchema, extensionSchema, defaultInstance);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T newInstance() {
+ return (T) defaultInstance.newBuilderForType().buildPartial();
+ }
+
+ @Override
+ public boolean equals(T message, T other) {
+ Object messageUnknown = unknownFieldSchema.getFromMessage(message);
+ Object otherUnknown = unknownFieldSchema.getFromMessage(other);
+ if (!messageUnknown.equals(otherUnknown)) {
+ return false;
+ }
+ if (hasExtensions) {
+ FieldSet<?> messageExtensions = extensionSchema.getExtensions(message);
+ FieldSet<?> otherExtensions = extensionSchema.getExtensions(other);
+ return messageExtensions.equals(otherExtensions);
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode(T message) {
+ int hashCode = unknownFieldSchema.getFromMessage(message).hashCode();
+ if (hasExtensions) {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ hashCode = (hashCode * 53) + extensions.hashCode();
+ }
+ return hashCode;
+ }
+
+ @Override
+ public void mergeFrom(T message, T other) {
+ SchemaUtil.mergeUnknownFields(unknownFieldSchema, message, other);
+ if (hasExtensions) {
+ SchemaUtil.mergeExtensions(extensionSchema, message, other);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void writeTo(T message, Writer writer) throws IOException {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ Iterator<?> iterator = extensions.iterator();
+ while (iterator.hasNext()) {
+ Entry<?, ?> extension = (Entry<?, ?>) iterator.next();
+ FieldSet.FieldDescriptorLite<?> fd = (FieldSet.FieldDescriptorLite<?>) extension.getKey();
+ if (fd.getLiteJavaType() != WireFormat.JavaType.MESSAGE || fd.isRepeated() || fd.isPacked()) {
+ throw new IllegalStateException("Found invalid MessageSet item.");
+ }
+ if (extension instanceof LazyField.LazyEntry) {
+ writer.writeMessageSetItem(
+ fd.getNumber(), ((LazyField.LazyEntry) extension).getField().toByteString());
+ } else {
+ writer.writeMessageSetItem(fd.getNumber(), extension.getValue());
+ }
+ }
+ writeUnknownFieldsHelper(unknownFieldSchema, message, writer);
+ }
+
+ /**
+ * A helper method for wildcard capture of {@code unknownFieldSchema}. See:
+ * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
+ */
+ private <UT, UB> void writeUnknownFieldsHelper(
+ UnknownFieldSchema<UT, UB> unknownFieldSchema, T message, Writer writer) throws IOException {
+ unknownFieldSchema.writeAsMessageSetTo(unknownFieldSchema.getFromMessage(message), writer);
+ }
+
+ @SuppressWarnings("ReferenceEquality")
+ @Override
+ public void mergeFrom(
+ T message, byte[] data, int position, int limit, ArrayDecoders.Registers registers)
+ throws IOException {
+ UnknownFieldSetLite unknownFields = ((GeneratedMessageLite) message).unknownFields;
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ ((GeneratedMessageLite) message).unknownFields = unknownFields;
+ }
+ final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions =
+ ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable();
+ GeneratedMessageLite.GeneratedExtension<?, ?> extension = null;
+ while (position < limit) {
+ position = ArrayDecoders.decodeVarint32(data, position, registers);
+ final int startTag = registers.int1;
+ if (startTag != WireFormat.MESSAGE_SET_ITEM_TAG) {
+ if (WireFormat.getTagWireType(startTag) == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ extension =
+ (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionSchema.findExtensionByNumber(
+ registers.extensionRegistry, defaultInstance,
+ WireFormat.getTagFieldNumber(startTag));
+ if (extension != null) {
+ position =
+ ArrayDecoders.decodeMessageField(
+ Protobuf.getInstance().schemaFor(
+ extension.getMessageDefaultInstance().getClass()),
+ data, position, limit, registers);
+ extensions.setField(extension.descriptor, registers.object1);
+ } else {
+ position =
+ ArrayDecoders.decodeUnknownField(
+ startTag, data, position, limit, unknownFields, registers);
+ }
+ } else {
+ position = ArrayDecoders.skipField(startTag, data, position, limit, registers);
+ }
+ continue;
+ }
+
+ int typeId = 0;
+ ByteString rawBytes = null;
+
+ while (position < limit) {
+ position = ArrayDecoders.decodeVarint32(data, position, registers);
+ final int tag = registers.int1;
+ final int number = WireFormat.getTagFieldNumber(tag);
+ final int wireType = WireFormat.getTagWireType(tag);
+ switch (number) {
+ case WireFormat.MESSAGE_SET_TYPE_ID:
+ if (wireType == WireFormat.WIRETYPE_VARINT) {
+ position = ArrayDecoders.decodeVarint32(data, position, registers);
+ typeId = registers.int1;
+ extension =
+ (GeneratedMessageLite.GeneratedExtension<?, ?>) extensionSchema
+ .findExtensionByNumber(registers.extensionRegistry, defaultInstance, typeId);
+ continue;
+ }
+ break;
+ case WireFormat.MESSAGE_SET_MESSAGE:
+ if (extension != null) {
+ position = ArrayDecoders.decodeMessageField(
+ Protobuf.getInstance().schemaFor(
+ extension.getMessageDefaultInstance().getClass()),
+ data, position, limit, registers);
+ extensions.setField(extension.descriptor, registers.object1);
+ continue;
+ } else {
+ if (wireType == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ position = ArrayDecoders.decodeBytes(data, position, registers);
+ rawBytes = (ByteString) registers.object1;
+ continue;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (tag == WireFormat.MESSAGE_SET_ITEM_END_TAG) {
+ break;
+ }
+ position = ArrayDecoders.skipField(tag, data, position, limit, registers);
+ }
+
+ if (rawBytes != null) {
+ unknownFields.storeField(
+ WireFormat.makeTag(typeId, WireFormat.WIRETYPE_LENGTH_DELIMITED), rawBytes);
+ }
+ }
+ if (position != limit) {
+ throw InvalidProtocolBufferException.parseFailure();
+ }
+ }
+
+ @Override
+ public void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ mergeFromHelper(unknownFieldSchema, extensionSchema, message, reader, extensionRegistry);
+ }
+
+ /**
+ * A helper method for wildcard capture of {@code unknownFieldSchema}. See:
+ * https://docs.oracle.com/javase/tutorial/java/generics/capture.html
+ */
+ @SuppressWarnings("unchecked")
+ private <UT, UB, ET extends FieldSet.FieldDescriptorLite<ET>> void mergeFromHelper(
+ UnknownFieldSchema<UT, UB> unknownFieldSchema,
+ ExtensionSchema<ET> extensionSchema,
+ T message,
+ Reader reader,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ UB unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
+ FieldSet<ET> extensions = extensionSchema.getMutableExtensions(message);
+ try {
+ while (true) {
+ final int number = reader.getFieldNumber();
+ if (number == Reader.READ_DONE) {
+ return;
+ }
+ if (parseMessageSetItemOrUnknownField(
+ reader,
+ extensionRegistry,
+ extensionSchema,
+ extensions,
+ unknownFieldSchema,
+ unknownFields)) {
+ continue;
+ }
+ // Done reading.
+ return;
+ }
+ } finally {
+ unknownFieldSchema.setBuilderToMessage(message, unknownFields);
+ }
+ }
+
+ @Override
+ public void makeImmutable(T message) {
+ unknownFieldSchema.makeImmutable(message);
+ extensionSchema.makeImmutable(message);
+ }
+
+ private <UT, UB, ET extends FieldSet.FieldDescriptorLite<ET>>
+ boolean parseMessageSetItemOrUnknownField(
+ Reader reader,
+ ExtensionRegistryLite extensionRegistry,
+ ExtensionSchema<ET> extensionSchema,
+ FieldSet<ET> extensions,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema,
+ UB unknownFields)
+ throws IOException {
+ int startTag = reader.getTag();
+ if (startTag != WireFormat.MESSAGE_SET_ITEM_TAG) {
+ if (WireFormat.getTagWireType(startTag) == WireFormat.WIRETYPE_LENGTH_DELIMITED) {
+ Object extension =
+ extensionSchema.findExtensionByNumber(
+ extensionRegistry, defaultInstance, WireFormat.getTagFieldNumber(startTag));
+ if (extension != null) {
+ extensionSchema.parseLengthPrefixedMessageSetItem(
+ reader, extension, extensionRegistry, extensions);
+ return true;
+ } else {
+ return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader);
+ }
+ } else {
+ return reader.skipField();
+ }
+ }
+
+ // 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"
+ Object 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.
+ loop:
+ while (true) {
+ final int number = reader.getFieldNumber();
+ if (number == Reader.READ_DONE) {
+ break;
+ }
+
+ final int tag = reader.getTag();
+ if (tag == WireFormat.MESSAGE_SET_TYPE_ID_TAG) {
+ typeId = reader.readUInt32();
+ extension =
+ extensionSchema.findExtensionByNumber(extensionRegistry, defaultInstance, typeId);
+ continue;
+ } else if (tag == WireFormat.MESSAGE_SET_MESSAGE_TAG) {
+ if (extension != null) {
+ extensionSchema.parseLengthPrefixedMessageSetItem(
+ reader, extension, extensionRegistry, extensions);
+ continue;
+ }
+ // We haven't seen a type ID yet or we want parse message lazily.
+ rawBytes = reader.readBytes();
+ continue;
+ } else {
+ if (!reader.skipField()) {
+ break loop; // End of group
+ }
+ }
+ }
+
+ if (reader.getTag() != WireFormat.MESSAGE_SET_ITEM_END_TAG) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+
+ // If there are any rawBytes left, it means the message content appears before the type ID.
+ if (rawBytes != null) {
+ if (extension != null) { // We known the type
+ // TODO(xiaofeng): Instead of reading into a temporary ByteString, maybe there is a way
+ // to read directly from Reader to the submessage?
+ extensionSchema.parseMessageSetItem(rawBytes, extension, extensionRegistry, extensions);
+ } else {
+ unknownFieldSchema.addLengthDelimited(unknownFields, typeId, rawBytes);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public final boolean isInitialized(T message) {
+ FieldSet<?> extensions = extensionSchema.getExtensions(message);
+ return extensions.isInitialized();
+ }
+
+ @Override
+ public int getSerializedSize(T message) {
+ int size = 0;
+
+ size += getUnknownFieldsSerializedSize(unknownFieldSchema, message);
+
+ if (hasExtensions) {
+ size += extensionSchema.getExtensions(message).getMessageSetSerializedSize();
+ }
+
+ return size;
+ }
+
+ private <UT, UB> int getUnknownFieldsSerializedSize(
+ UnknownFieldSchema<UT, UB> schema, T message) {
+ UT unknowns = schema.getFromMessage(message);
+ return schema.getSerializedSizeAsMessageSet(unknowns);
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java
new file mode 100755
index 000000000..f2dbb8ef9
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java
@@ -0,0 +1,36 @@
+// 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 NewInstanceSchema {
+ /** Create a new message instance given the default instance of the message type. */
+ Object newInstance(Object defaultInstance);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java
new file mode 100755
index 000000000..3433b657e
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java
@@ -0,0 +1,39 @@
+// 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;
+
+final class NewInstanceSchemaFull implements NewInstanceSchema {
+ @Override
+ public Object newInstance(Object defaultInstance) {
+ return ((GeneratedMessageV3) defaultInstance)
+ .newInstance(GeneratedMessageV3.UnusedPrivateParameter.INSTANCE);
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java
new file mode 100755
index 000000000..9b9226676
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java
@@ -0,0 +1,39 @@
+// 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;
+
+final class NewInstanceSchemaLite implements NewInstanceSchema {
+ @Override
+ public Object newInstance(Object defaultInstance) {
+ return ((GeneratedMessageLite) defaultInstance)
+ .dynamicMethod(GeneratedMessageLite.MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java
new file mode 100755
index 000000000..eff45f67b
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java
@@ -0,0 +1,53 @@
+// 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;
+
+final class NewInstanceSchemas {
+ private static final NewInstanceSchema FULL_SCHEMA = loadSchemaForFullRuntime();
+ private static final NewInstanceSchema LITE_SCHEMA = new NewInstanceSchemaLite();
+
+ static NewInstanceSchema full() {
+ return FULL_SCHEMA;
+ }
+
+ static NewInstanceSchema lite() {
+ return LITE_SCHEMA;
+ }
+
+ private static NewInstanceSchema loadSchemaForFullRuntime() {
+ try {
+ Class<?> clazz = Class.forName("com.google.protobuf.NewInstanceSchemaFull");
+ return (NewInstanceSchema) clazz.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/OneofInfo.java b/java/core/src/main/java/com/google/protobuf/OneofInfo.java
new file mode 100755
index 000000000..bc518fcad
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/OneofInfo.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.reflect.Field;
+
+/** Information for a oneof within a protobuf message. */
+// TODO(nathanmittler): make this private once all of experimental code is migrated to protobuf.
+@ExperimentalApi
+final class OneofInfo {
+ private final int id;
+ private final Field caseField;
+ private final Field valueField;
+
+ public OneofInfo(int id, Field caseField, Field valueField) {
+ this.id = id;
+ this.caseField = caseField;
+ this.valueField = valueField;
+ }
+
+ /**
+ * Returns the unique identifier of the oneof within the message. This is really just an index
+ * starting at zero.
+ */
+ public int getId() {
+ return id;
+ }
+
+ /** The {@code int} field containing the field number of the currently active member. */
+ public Field getCaseField() {
+ return caseField;
+ }
+
+ /** The {@link Object} field containing the value of the currently active member. */
+ public Field getValueField() {
+ return valueField;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java b/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java
new file mode 100755
index 000000000..851b839f6
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ProtoSyntax.java
@@ -0,0 +1,38 @@
+// 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;
+
+/** Represents the syntax version of the message. */
+@ExperimentalApi
+public enum ProtoSyntax {
+ PROTO2,
+ PROTO3;
+}
diff --git a/java/core/src/main/java/com/google/protobuf/Protobuf.java b/java/core/src/main/java/com/google/protobuf/Protobuf.java
new file mode 100755
index 000000000..adaa7fa8f
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/Protobuf.java
@@ -0,0 +1,152 @@
+// 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.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Main runtime interface for protobuf. Applications should interact with this interface (rather
+ * than directly accessing internal APIs) in order to perform operations on protobuf messages.
+ */
+@ExperimentalApi
+final class Protobuf {
+ private static final Protobuf INSTANCE = new Protobuf();
+
+ private final SchemaFactory schemaFactory;
+
+ // TODO(nathanmittler): Consider using ClassValue instead.
+ private final ConcurrentMap<Class<?>, Schema<?>> schemaCache =
+ new ConcurrentHashMap<Class<?>, Schema<?>>();
+
+ /** Gets the singleton instance of the Protobuf runtime. */
+ public static Protobuf getInstance() {
+ return INSTANCE;
+ }
+
+ /** Writes the given message to the target {@link Writer}. */
+ public <T> void writeTo(T message, Writer writer) throws IOException {
+ schemaFor(message).writeTo(message, writer);
+ }
+
+ /** Reads fields from the given {@link Reader} and merges them into the message. */
+ public <T> void mergeFrom(T message, Reader reader) throws IOException {
+ mergeFrom(message, reader, ExtensionRegistryLite.getEmptyRegistry());
+ }
+
+ /** Reads fields from the given {@link Reader} and merges them into the message. */
+ public <T> void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
+ schemaFor(message).mergeFrom(message, reader, extensionRegistry);
+ }
+
+ /** Marks repeated/map/extension/unknown fields as immutable. */
+ public <T> void makeImmutable(T message) {
+ schemaFor(message).makeImmutable(message);
+ }
+
+ /**
+ * Checks if all required fields are set. TODO(xiaofeng): Make this package private when the tests
+ * are moved to protobuf package.
+ */
+ public <T> boolean isInitialized(T message) {
+ return schemaFor(message).isInitialized(message);
+ }
+
+ /** Gets the schema for the given message type. */
+ public <T> Schema<T> schemaFor(Class<T> messageType) {
+ checkNotNull(messageType, "messageType");
+ @SuppressWarnings("unchecked")
+ Schema<T> schema = (Schema<T>) schemaCache.get(messageType);
+ if (schema == null) {
+ schema = schemaFactory.createSchema(messageType);
+ @SuppressWarnings("unchecked")
+ Schema<T> previous = (Schema<T>) registerSchema(messageType, schema);
+ if (previous != null) {
+ // A new schema was registered by another thread.
+ schema = previous;
+ }
+ }
+ return schema;
+ }
+
+ /** Gets the schema for the given message. */
+ @SuppressWarnings("unchecked")
+ public <T> Schema<T> schemaFor(T message) {
+ return schemaFor((Class<T>) message.getClass());
+ }
+
+ /**
+ * Registers the given schema for the message type only if a schema was not already registered.
+ *
+ * @param messageType the type of message on which the schema operates.
+ * @param schema the schema for the message type.
+ * @return the previously registered schema, or {@code null} if the given schema was successfully
+ * registered.
+ */
+ public Schema<?> registerSchema(Class<?> messageType, Schema<?> schema) {
+ checkNotNull(messageType, "messageType");
+ checkNotNull(schema, "schema");
+ return schemaCache.putIfAbsent(messageType, schema);
+ }
+
+ /**
+ * Visible for testing only. Registers the given schema for the message type. If a schema was
+ * previously registered, it will be replaced by the provided schema.
+ *
+ * @param messageType the type of message on which the schema operates.
+ * @param schema the schema for the message type.
+ * @return the previously registered schema, or {@code null} if no schema was registered
+ * previously.
+ */
+ public Schema<?> registerSchemaOverride(Class<?> messageType, Schema<?> schema) {
+ checkNotNull(messageType, "messageType");
+ checkNotNull(schema, "schema");
+ return schemaCache.put(messageType, schema);
+ }
+
+ private Protobuf() {
+ schemaFactory = new ManifestSchemaFactory();
+ }
+
+ int getTotalSchemaSize() {
+ int result = 0;
+ for (Schema<?> schema : schemaCache.values()) {
+ if (schema instanceof MessageSchema) {
+ result += ((MessageSchema) schema).getSchemaSize();
+ }
+ }
+ return result;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufLists.java b/java/core/src/main/java/com/google/protobuf/ProtobufLists.java
new file mode 100755
index 000000000..271c849b4
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/ProtobufLists.java
@@ -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.
+
+package com.google.protobuf;
+
+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;
+
+/** Utility class for construction of lists that extend {@link ProtobufList}. */
+@ExperimentalApi
+final class ProtobufLists {
+ private ProtobufLists() {}
+
+ public static <E> ProtobufList<E> emptyProtobufList() {
+ return ProtobufArrayList.emptyList();
+ }
+
+ public static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
+ public static BooleanList emptyBooleanList() {
+ return BooleanArrayList.emptyList();
+ }
+
+ public static BooleanList newBooleanList() {
+ return new BooleanArrayList();
+ }
+
+ public static IntList emptyIntList() {
+ return IntArrayList.emptyList();
+ }
+
+ public static IntList newIntList() {
+ return new IntArrayList();
+ }
+
+ public static LongList emptyLongList() {
+ return LongArrayList.emptyList();
+ }
+
+ public static LongList newLongList() {
+ return new LongArrayList();
+ }
+
+ public static FloatList emptyFloatList() {
+ return FloatArrayList.emptyList();
+ }
+
+ public static FloatList newFloatList() {
+ return new FloatArrayList();
+ }
+
+ public static DoubleList emptyDoubleList() {
+ return DoubleArrayList.emptyList();
+ }
+
+ public static DoubleList newDoubleList() {
+ return new DoubleArrayList();
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.java
new file mode 100755
index 000000000..3982d2e22
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/RawMessageInfo.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;
+
+/**
+ * RawMessageInfo stores the same amount of information as {@link MessageInfo} but in a more compact
+ * format.
+ */
+final class RawMessageInfo implements MessageInfo {
+
+ private final MessageLite defaultInstance;
+
+ /**
+ * The compact format packs everything in a String object and a Object[] array. The String object
+ * is encoded with field number, field type, hasbits offset, oneof index, etc., whereas the
+ * Object[] array contains field references, class references, instance references, etc.
+ * BEGIN GOOGLE-INTERNAL
+ *
+ * See
+ * https://docs.google.com/document/d/1_z6-tIa31Pq6MUi_79eA5S6214J13idRbAHTgn3vqXY/edit#heading=h.cifnozjwpoe9
+ * for more information.
+ * END GOOGLE-INTERNAL
+ *
+ * <p>The String object encodes a sequence of integers into UTF-16 characters. For each int, it
+ * will be encoding into 1 to 3 UTF-16 characters depending on its unsigned value:
+ *
+ * <ul>
+ * <li>1 char: [c1: 0x0000 - 0xD7FF] = int of the same value.
+ * <li>2 chars: [c1: 0xE000 - 0xFFFF], [c2: 0x0000 - 0xD7FF] = (c2 << 13) | (c1 & 0x1FFF)
+ * <li>3 chars: [c1: 0xE000 - 0xFFFF], [c2: 0xE000 - 0xFFFF], [c3: 0x0000 - 0xD7FF] = (c3 << 26)
+ * | ((c2 & 0x1FFF) << 13) | (c1 & 0x1FFF)
+ * </ul>
+ *
+ * <p>Note that we don't use UTF-16 surrogate pairs [0xD800 - 0xDFFF] because they have to come in
+ * pairs to form a valid UTF-16char sequence and don't help us encode values more efficiently.
+ *
+ * <p>The integer sequence encoded in the String object has the following layout:
+ *
+ * <ul>
+ * <li>[0]: flags, flags & 0x1 = is proto2?, flags & 0x2 = is message?.
+ * <li>[1]: field count, if 0, this is the end of the integer sequence and the corresponding
+ * Object[] array should be null.
+ * <li>[2]: oneof count
+ * <li>[3]: hasbits count, how many hasbits integers are generated.
+ * <li>[4]: min field number
+ * <li>[5]: max field number
+ * <li>[6]: total number of entries need to allocate
+ * <li>[7]: map field count
+ * <li>[8]: repeated field count, this doesn't include map fields.
+ * <li>[9]: size of checkInitialized array
+ * <li>[...]: field entries
+ * </ul>
+ *
+ * <p>Each field entry starts with a field number and the field type:
+ *
+ * <ul>
+ * <li>[0]: field number
+ * <li>[1]: field type with extra bits:
+ * <ul>
+ * <li>v & 0xFF = field type as defined in the FieldType class
+ * <li>v & 0x100 = is required?
+ * <li>v & 0x200 = is checkUtf8?
+ * <li>v & 0x400 = needs isInitialized check?
+ * <li>v & 0x800 = is map field with proto2 enum value?
+ * </ul>
+ * </ul>
+ *
+ * If the file is proto2 and this is a singular field:
+ *
+ * <ul>
+ * <li>[2]: hasbits offset
+ * </ul>
+ *
+ * If the field is in an oneof:
+ *
+ * <ul>
+ * <li>[2]: oenof index
+ * </ul>
+ *
+ * For other types, the field entry only has field number and field type.
+ *
+ * <p>The Object[] array has 3 sections:
+ *
+ * <ul>
+ * <li>---- oneof section ----
+ * <ul>
+ * <li>[0]: value field for oneof 1.
+ * <li>[1]: case field for oneof 1.
+ * <li>...
+ * <li>[.]: value field for oneof n.
+ * <li>[.]: case field for oneof n.
+ * </ul>
+ * <li>---- hasbits section ----
+ * <ul>
+ * <li>[.]: hasbits field 1
+ * <li>[.]: hasbits field 2
+ * <li>...
+ * <li>[.]: hasbits field n
+ * </ul>
+ * <li>---- field section ----
+ * <ul>
+ * <li>[...]: field entries
+ * </ul>
+ * </ul>
+ *
+ * <p>In the Object[] array, field entries are ordered in the same way as field entries in the
+ * String object. The size of each entry is determined by the field type.
+ *
+ * <ul>
+ * <li>Oneof field:
+ * <ul>
+ * <li>Oneof message field:
+ * <ul>
+ * <li>[0]: message class reference.
+ * </ul>
+ * <li>Oneof enum fieldin proto2:
+ * <ul>
+ * <li>[0]: EnumLiteMap
+ * </ul>
+ * <li>For all other oneof fields, field entry in the Object[] array is empty.
+ * </ul>
+ * <li>Repeated message field:
+ * <ul>
+ * <li>[0]: field reference
+ * <li>[1]: message class reference
+ * </ul>
+ * <li>Proto2 singular/repeated enum field:
+ * <ul>
+ * <li>[0]: field reference
+ * <li>[1]: EnumLiteMap
+ * </ul>
+ * <li>Map field with a proto2 enum value:
+ * <ul>
+ * <li>[0]: field reference
+ * <li>[1]: map default entry instance
+ * <li>[2]: EnumLiteMap
+ * </ul>
+ * <li>Map field with other value types:
+ * <ul>
+ * <li>[0]: field reference
+ * <li>[1]: map default entry instance
+ * </ul>
+ * <li>All other field type:
+ * <ul>
+ * <li>[0]: field reference
+ * </ul>
+ * </ul>
+ *
+ * <p>In order to read the field info from this compact format, a reader needs to progress through
+ * the String object and the Object[] array simultaneously.
+ */
+ private final String info;
+
+ private final Object[] objects;
+ private final int flags;
+
+ RawMessageInfo(MessageLite defaultInstance, String info, Object[] objects) {
+ this.defaultInstance = defaultInstance;
+ this.info = info;
+ this.objects = objects;
+ int position = 0;
+ int value = (int) info.charAt(position++);
+ if (value < 0xD800) {
+ flags = value;
+ } else {
+ int result = value & 0x1FFF;
+ int shift = 13;
+ while ((value = info.charAt(position++)) >= 0xD800) {
+ result |= (value & 0x1FFF) << shift;
+ shift += 13;
+ }
+ flags = result | (value << shift);
+ }
+ }
+
+ String getStringInfo() {
+ return info;
+ }
+
+ Object[] getObjects() {
+ return objects;
+ }
+
+ @Override
+ public MessageLite getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ @Override
+ public ProtoSyntax getSyntax() {
+ return (flags & 0x1) == 0x1 ? ProtoSyntax.PROTO2 : ProtoSyntax.PROTO3;
+ }
+
+ @Override
+ public boolean isMessageSetWireFormat() {
+ return (flags & 0x2) == 0x2;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/Reader.java b/java/core/src/main/java/com/google/protobuf/Reader.java
new file mode 100755
index 000000000..705096f2d
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/Reader.java
@@ -0,0 +1,379 @@
+// 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.List;
+import java.util.Map;
+
+/** A reader of fields from a serialized protobuf message. */
+// TODO(nathanmittler): Refactor to allow the reader to allocate properly sized lists.
+@ExperimentalApi
+interface Reader {
+ /** Value used to indicate that the end of input has been reached. */
+ int READ_DONE = Integer.MAX_VALUE;
+
+ /** Value used to indicate that the reader does not know the tag about the field. */
+ int TAG_UNKNOWN = 0;
+
+ boolean shouldDiscardUnknownFields();
+
+ /**
+ * Gets the field number for the current field being read.
+ *
+ * <p>TODO(liujisi): Rename it to make it more explicit about the side effect on the underlying
+ * buffer.
+ *
+ * @return the current field number or {@link #READ_DONE} if the end of input has been reached.
+ */
+ int getFieldNumber() throws IOException;
+
+ /**
+ * Gets the wire tag of the current field.
+ *
+ * @return the current wire tag or {@link #TAG_UNKNOWN} if the reader does not know the tag of the
+ * current field.
+ */
+ int getTag();
+
+ /**
+ * Skips the current field and advances the reader to the next field.
+ *
+ * @return {@code true} if there are more fields or {@code false} if the end of input has been
+ * reached.
+ */
+ boolean skipField() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code DOUBLE} and advances the reader to the next
+ * field.
+ */
+ double readDouble() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code FLOAT} and advances the reader to the next
+ * field.
+ */
+ float readFloat() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code UINT64} and advances the reader to the next
+ * field.
+ */
+ long readUInt64() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code INT64} and advances the reader to the next
+ * field.
+ */
+ long readInt64() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code INT32} and advances the reader to the next
+ * field.
+ */
+ int readInt32() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code FIXED64} and advances the reader to the next
+ * field.
+ */
+ long readFixed64() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code FIXED32} and advances the reader to the next
+ * field.
+ */
+ int readFixed32() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code BOOL} and advances the reader to the next
+ * field.
+ */
+ boolean readBool() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code STRING} and advances the reader to the next
+ * field. If the stream contains malformed UTF-8, replace the offending bytes with the standard
+ * UTF-8 replacement character.
+ */
+ String readString() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code STRING} and advances the reader to the next
+ * field. If the stream contains malformed UTF-8, throw exception {@link
+ * InvalidProtocolBufferException}.
+ */
+ String readStringRequireUtf8() throws IOException;
+
+ // TODO(yilunchong): the lack of other opinions for whether to expose this on the interface
+ <T> T readMessageBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code MESSAGE} and advances the reader to the next
+ * field.
+ */
+ <T> T readMessage(Class<T> clazz, ExtensionRegistryLite extensionRegistry) throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code GROUP} and advances the reader to the next
+ * field.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ <T> T readGroup(Class<T> clazz, ExtensionRegistryLite extensionRegistry) throws IOException;
+
+ // TODO(yilunchong): the lack of other opinions for whether to expose this on the interface
+ @Deprecated
+ <T> T readGroupBySchemaWithCheck(Schema<T> schema, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code BYTES} and advances the reader to the next
+ * field.
+ */
+ ByteString readBytes() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code UINT32} and advances the reader to the next
+ * field.
+ */
+ int readUInt32() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code ENUM} and advances the reader to the next
+ * field.
+ */
+ int readEnum() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code SFIXED32} and advances the reader to the next
+ * field.
+ */
+ int readSFixed32() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code SFIXED64} and advances the reader to the next
+ * field.
+ */
+ long readSFixed64() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code SINT32} and advances the reader to the next
+ * field.
+ */
+ int readSInt32() throws IOException;
+
+ /**
+ * Reads and returns the next field of type {@code SINT64} and advances the reader to the next
+ * field.
+ */
+ long readSInt64() throws IOException;
+
+ /**
+ * Reads the next field of type {@code DOUBLE_LIST} or {@code DOUBLE_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readDoubleList(List<Double> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code FLOAT_LIST} or {@code FLOAT_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readFloatList(List<Float> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code UINT64_LIST} or {@code UINT64_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readUInt64List(List<Long> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code INT64_LIST} or {@code INT64_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readInt64List(List<Long> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code INT32_LIST} or {@code INT32_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readInt32List(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code FIXED64_LIST} or {@code FIXED64_LIST_PACKED} and advances
+ * the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readFixed64List(List<Long> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code FIXED32_LIST} or {@code FIXED32_LIST_PACKED} and advances
+ * the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readFixed32List(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code BOOL_LIST} or {@code BOOL_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readBoolList(List<Boolean> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readStringList(List<String> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code STRING_LIST} and advances the reader to the next field. If
+ * the stream contains malformed UTF-8, throw exception {@link InvalidProtocolBufferException}.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readStringListRequireUtf8(List<String> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code MESSAGE_LIST} and advances the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ * @param targetType the type of the elements stored in the {@code target} list.
+ */
+ <T> void readMessageList(
+ List<T> target, Schema<T> schema, ExtensionRegistryLite extensionRegistry) throws IOException;
+
+ <T> void readMessageList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Reads the next field of type {@code GROUP_LIST} and advances the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ * @param targetType the type of the elements stored in the {@code target} list.
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ <T> void readGroupList(
+ List<T> target, Class<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ @Deprecated
+ <T> void readGroupList(
+ List<T> target, Schema<T> targetType, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Reads the next field of type {@code BYTES_LIST} and advances the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readBytesList(List<ByteString> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code UINT32_LIST} or {@code UINT32_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readUInt32List(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code ENUM_LIST} or {@code ENUM_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readEnumList(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code SFIXED32_LIST} or {@code SFIXED32_LIST_PACKED} and advances
+ * the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readSFixed32List(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code SFIXED64_LIST} or {@code SFIXED64_LIST_PACKED} and advances
+ * the reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readSFixed64List(List<Long> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code SINT32_LIST} or {@code SINT32_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readSInt32List(List<Integer> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code SINT64_LIST} or {@code SINT64_LIST_PACKED} and advances the
+ * reader to the next field.
+ *
+ * @param target the list that will receive the read values.
+ */
+ void readSInt64List(List<Long> target) throws IOException;
+
+ /**
+ * Reads the next field of type {@code MAP} and advances the reader to the next field.
+ *
+ * @param target the mutable map that will receive the read values.
+ * @param mapDefaultEntry the default entry of the map field.
+ * @param extensionRegistry the extension registry for parsing message value fields.
+ */
+ <K, V> void readMap(
+ Map<K, V> target,
+ MapEntryLite.Metadata<K, V> mapDefaultEntry,
+ ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+}
diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
index c3bec7b1a..f294df3df 100644
--- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -445,6 +445,11 @@ final class RopeByteString extends ByteString {
right.writeTo(output);
}
+ @Override
+ void writeToReverse(ByteOutput output) throws IOException {
+ right.writeToReverse(output);
+ left.writeToReverse(output);
+ }
@Override
protected String toStringInternal(Charset charset) {
diff --git a/java/core/src/main/java/com/google/protobuf/Schema.java b/java/core/src/main/java/com/google/protobuf/Schema.java
new file mode 100755
index 000000000..d0e1e26e5
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/Schema.java
@@ -0,0 +1,85 @@
+// 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.ArrayDecoders.Registers;
+import java.io.IOException;
+
+/**
+ * A runtime schema for a single protobuf message. A schema provides operations on message instances
+ * such as serialization/deserialization.
+ */
+@ExperimentalApi
+interface Schema<T> {
+ /** Writes the given message to the target {@link Writer}. */
+ void writeTo(T message, Writer writer) throws IOException;
+
+ /**
+ * Reads fields from the given {@link Reader} and merges them into the message. It doesn't make
+ * the message immutable after parsing is done. To make the message immutable, use {@link
+ * #makeImmutable}.
+ */
+ void mergeFrom(T message, Reader reader, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ /**
+ * Like the above but parses from a byte[] without extensions. Entry point of fast path. Note that
+ * this method may throw IndexOutOfBoundsException if the input data is not valid protobuf wire
+ * format. Protobuf public API methods should catch and convert that exception to
+ * InvalidProtocolBufferException.
+ */
+ void mergeFrom(T message, byte[] data, int position, int limit, Registers registers)
+ throws IOException;
+
+ /** Marks repeated/map/extension/unknown fields as immutable. */
+ void makeImmutable(T message);
+
+ /** Checks whether all required fields are set. */
+ boolean isInitialized(T message);
+
+ /** Creates a new instance of the message class. */
+ T newInstance();
+
+ /** Determine of the two messages are equal. */
+ boolean equals(T message, T other);
+
+ /** Compute a hashCode for the message. */
+ int hashCode(T message);
+
+ /**
+ * Merge values from {@code other} into {@code message}. This method doesn't make the message
+ * immutable. To make the message immutable after merging, use {@link #makeImmutable}.
+ */
+ void mergeFrom(T message, T other);
+
+ /** Compute the serialized size of the message. */
+ int getSerializedSize(T message);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/SchemaFactory.java b/java/core/src/main/java/com/google/protobuf/SchemaFactory.java
new file mode 100755
index 000000000..cf38dd699
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/SchemaFactory.java
@@ -0,0 +1,38 @@
+// 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 factory that manufactures {@link Schema} instances for protobuf messages. */
+@ExperimentalApi
+interface SchemaFactory {
+ /** Creates a schema instance for the given protobuf message type. */
+ <T> Schema<T> createSchema(Class<T> messageType);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/SchemaUtil.java b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java
new file mode 100755
index 000000000..50957fcfd
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/SchemaUtil.java
@@ -0,0 +1,991 @@
+// 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.FieldSet.FieldDescriptorLite;
+import com.google.protobuf.Internal.EnumLiteMap;
+import com.google.protobuf.Internal.EnumVerifier;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.List;
+import java.util.RandomAccess;
+
+/** Helper methods used by schemas. */
+@ExperimentalApi
+final class SchemaUtil {
+ private static final Class<?> GENERATED_MESSAGE_CLASS = getGeneratedMessageClass();
+ private static final UnknownFieldSchema<?, ?> PROTO2_UNKNOWN_FIELD_SET_SCHEMA =
+ getUnknownFieldSetSchema(false);
+ private static final UnknownFieldSchema<?, ?> PROTO3_UNKNOWN_FIELD_SET_SCHEMA =
+ getUnknownFieldSetSchema(true);
+ private static final UnknownFieldSchema<?, ?> UNKNOWN_FIELD_SET_LITE_SCHEMA =
+ new UnknownFieldSetLiteSchema();
+
+ private static final int DEFAULT_LOOK_UP_START_NUMBER = 40;
+
+ private SchemaUtil() {}
+
+ /**
+ * Requires that the given message extend {@link com.google.protobuf.GeneratedMessageV3} or {@link
+ * GeneratedMessageLite}.
+ */
+ public static void requireGeneratedMessage(Class<?> messageType) {
+ if (!GeneratedMessageLite.class.isAssignableFrom(messageType)
+ && GENERATED_MESSAGE_CLASS != null
+ && !GENERATED_MESSAGE_CLASS.isAssignableFrom(messageType)) {
+ throw new IllegalArgumentException(
+ "Message classes must extend GeneratedMessage or GeneratedMessageLite");
+ }
+ }
+
+ public static void writeDouble(int fieldNumber, double value, Writer writer) throws IOException {
+ if (Double.compare(value, 0.0) != 0) {
+ writer.writeDouble(fieldNumber, value);
+ }
+ }
+
+ public static void writeFloat(int fieldNumber, float value, Writer writer) throws IOException {
+ if (Float.compare(value, 0.0f) != 0) {
+ writer.writeFloat(fieldNumber, value);
+ }
+ }
+
+ public static void writeInt64(int fieldNumber, long value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeInt64(fieldNumber, value);
+ }
+ }
+
+ public static void writeUInt64(int fieldNumber, long value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeUInt64(fieldNumber, value);
+ }
+ }
+
+ public static void writeSInt64(int fieldNumber, long value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeSInt64(fieldNumber, value);
+ }
+ }
+
+ public static void writeFixed64(int fieldNumber, long value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeFixed64(fieldNumber, value);
+ }
+ }
+
+ public static void writeSFixed64(int fieldNumber, long value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeSFixed64(fieldNumber, value);
+ }
+ }
+
+ public static void writeInt32(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeInt32(fieldNumber, value);
+ }
+ }
+
+ public static void writeUInt32(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeUInt32(fieldNumber, value);
+ }
+ }
+
+ public static void writeSInt32(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeSInt32(fieldNumber, value);
+ }
+ }
+
+ public static void writeFixed32(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeFixed32(fieldNumber, value);
+ }
+ }
+
+ public static void writeSFixed32(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeSFixed32(fieldNumber, value);
+ }
+ }
+
+ public static void writeEnum(int fieldNumber, int value, Writer writer) throws IOException {
+ if (value != 0) {
+ writer.writeEnum(fieldNumber, value);
+ }
+ }
+
+ public static void writeBool(int fieldNumber, boolean value, Writer writer) throws IOException {
+ if (value) {
+ writer.writeBool(fieldNumber, true);
+ }
+ }
+
+ public static void writeString(int fieldNumber, Object value, Writer writer) throws IOException {
+ if (value instanceof String) {
+ writeStringInternal(fieldNumber, (String) value, writer);
+ } else {
+ writeBytes(fieldNumber, (ByteString) value, writer);
+ }
+ }
+
+ private static void writeStringInternal(int fieldNumber, String value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeString(fieldNumber, value);
+ }
+ }
+
+ public static void writeBytes(int fieldNumber, ByteString value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeBytes(fieldNumber, value);
+ }
+ }
+
+ public static void writeMessage(int fieldNumber, Object value, Writer writer) throws IOException {
+ if (value != null) {
+ writer.writeMessage(fieldNumber, value);
+ }
+ }
+
+ public static void writeDoubleList(
+ int fieldNumber, List<Double> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeDoubleList(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeFloatList(
+ int fieldNumber, List<Float> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeFloatList(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeInt64List(
+ int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeInt64List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeUInt64List(
+ int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeUInt64List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeSInt64List(
+ int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeSInt64List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeFixed64List(
+ int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeFixed64List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeSFixed64List(
+ int fieldNumber, List<Long> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeSFixed64List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeInt32List(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeInt32List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeUInt32List(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeUInt32List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeSInt32List(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeSInt32List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeFixed32List(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeFixed32List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeSFixed32List(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeSFixed32List(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeEnumList(
+ int fieldNumber, List<Integer> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeEnumList(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeBoolList(
+ int fieldNumber, List<Boolean> value, Writer writer, boolean packed) throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeBoolList(fieldNumber, value, packed);
+ }
+ }
+
+ public static void writeStringList(int fieldNumber, List<String> value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeStringList(fieldNumber, value);
+ }
+ }
+
+ public static void writeBytesList(int fieldNumber, List<ByteString> value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeBytesList(fieldNumber, value);
+ }
+ }
+
+ public static void writeMessageList(int fieldNumber, List<?> value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeMessageList(fieldNumber, value);
+ }
+ }
+
+ public static void writeMessageList(int fieldNumber, List<?> value, Writer writer, Schema schema)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeMessageList(fieldNumber, value, schema);
+ }
+ }
+
+ public static void writeLazyFieldList(int fieldNumber, List<?> value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ for (Object item : value) {
+ ((LazyFieldLite) item).writeTo(writer, fieldNumber);
+ }
+ }
+ }
+
+ public static void writeGroupList(int fieldNumber, List<?> value, Writer writer)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeGroupList(fieldNumber, value);
+ }
+ }
+
+ public static void writeGroupList(int fieldNumber, List<?> value, Writer writer, Schema schema)
+ throws IOException {
+ if (value != null && !value.isEmpty()) {
+ writer.writeGroupList(fieldNumber, value, schema);
+ }
+ }
+
+ static int computeSizeInt64ListNoTag(List<Long> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof LongArrayList) {
+ final LongArrayList primitiveList = (LongArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeInt64SizeNoTag(primitiveList.getLong(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeInt64SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeInt64List(int fieldNumber, List<Long> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeInt64ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (list.size() * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeUInt64ListNoTag(List<Long> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof LongArrayList) {
+ final LongArrayList primitiveList = (LongArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeUInt64SizeNoTag(primitiveList.getLong(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeUInt64SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeUInt64List(int fieldNumber, List<Long> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeUInt64ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeSInt64ListNoTag(List<Long> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof LongArrayList) {
+ final LongArrayList primitiveList = (LongArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeSInt64SizeNoTag(primitiveList.getLong(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeSInt64SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeSInt64List(int fieldNumber, List<Long> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeSInt64ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeEnumListNoTag(List<Integer> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof IntArrayList) {
+ final IntArrayList primitiveList = (IntArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeEnumSizeNoTag(primitiveList.getInt(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeEnumSizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeEnumList(int fieldNumber, List<Integer> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeEnumListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeInt32ListNoTag(List<Integer> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof IntArrayList) {
+ final IntArrayList primitiveList = (IntArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeInt32SizeNoTag(primitiveList.getInt(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeInt32SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeInt32List(int fieldNumber, List<Integer> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeInt32ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeUInt32ListNoTag(List<Integer> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof IntArrayList) {
+ final IntArrayList primitiveList = (IntArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeUInt32SizeNoTag(primitiveList.getInt(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeUInt32SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeUInt32List(int fieldNumber, List<Integer> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = computeSizeUInt32ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeSInt32ListNoTag(List<Integer> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = 0;
+
+ if (list instanceof IntArrayList) {
+ final IntArrayList primitiveList = (IntArrayList) list;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeSInt32SizeNoTag(primitiveList.getInt(i));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeSInt32SizeNoTag(list.get(i));
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeSInt32List(int fieldNumber, List<Integer> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+
+ int size = computeSizeSInt32ListNoTag(list);
+
+ if (packed) {
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(size);
+ } else {
+ return size + (length * CodedOutputStream.computeTagSize(fieldNumber));
+ }
+ }
+
+ static int computeSizeFixed32ListNoTag(List<?> list) {
+ return list.size() * WireFormat.FIXED32_SIZE;
+ }
+
+ static int computeSizeFixed32List(int fieldNumber, List<?> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ if (packed) {
+ int dataSize = length * WireFormat.FIXED32_SIZE;
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize);
+ } else {
+ return length * CodedOutputStream.computeFixed32Size(fieldNumber, 0);
+ }
+ }
+
+ static int computeSizeFixed64ListNoTag(List<?> list) {
+ return list.size() * WireFormat.FIXED64_SIZE;
+ }
+
+ static int computeSizeFixed64List(int fieldNumber, List<?> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ if (packed) {
+ final int dataSize = length * WireFormat.FIXED64_SIZE;
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(dataSize);
+ } else {
+ return length * CodedOutputStream.computeFixed64Size(fieldNumber, 0);
+ }
+ }
+
+ static int computeSizeBoolListNoTag(List<?> list) {
+ // bools are 1 byte varints
+ return list.size();
+ }
+
+ static int computeSizeBoolList(int fieldNumber, List<?> list, boolean packed) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ if (packed) {
+ // bools are 1 byte varints
+ return CodedOutputStream.computeTagSize(fieldNumber)
+ + CodedOutputStream.computeLengthDelimitedFieldSize(length);
+ } else {
+ return length * CodedOutputStream.computeBoolSize(fieldNumber, true);
+ }
+ }
+
+ static int computeSizeStringList(int fieldNumber, List<?> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = length * CodedOutputStream.computeTagSize(fieldNumber);
+ if (list instanceof LazyStringList) {
+ LazyStringList lazyList = ((LazyStringList) list);
+ for (int i = 0; i < length; i++) {
+ Object value = lazyList.getRaw(i);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSizeNoTag((String) value);
+ }
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ Object value = list.get(i);
+ if (value instanceof ByteString) {
+ size += CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
+ } else {
+ size += CodedOutputStream.computeStringSizeNoTag((String) value);
+ }
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeMessage(int fieldNumber, Object value, Schema schema) {
+ if (value instanceof LazyFieldLite) {
+ return CodedOutputStream.computeLazyFieldSize(fieldNumber, (LazyFieldLite) value);
+ } else {
+ return CodedOutputStream.computeMessageSize(fieldNumber, (MessageLite) value, schema);
+ }
+ }
+
+ static int computeSizeMessageList(int fieldNumber, List<?> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = length * CodedOutputStream.computeTagSize(fieldNumber);
+ for (int i = 0; i < length; i++) {
+ Object value = list.get(i);
+ if (value instanceof LazyFieldLite) {
+ size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value);
+ } else {
+ size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value);
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeMessageList(int fieldNumber, List<?> list, Schema schema) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = length * CodedOutputStream.computeTagSize(fieldNumber);
+ for (int i = 0; i < length; i++) {
+ Object value = list.get(i);
+ if (value instanceof LazyFieldLite) {
+ size += CodedOutputStream.computeLazyFieldSizeNoTag((LazyFieldLite) value);
+ } else {
+ size += CodedOutputStream.computeMessageSizeNoTag((MessageLite) value, schema);
+ }
+ }
+ return size;
+ }
+
+ static int computeSizeByteStringList(int fieldNumber, List<ByteString> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = length * CodedOutputStream.computeTagSize(fieldNumber);
+ for (int i = 0; i < list.size(); i++) {
+ size += CodedOutputStream.computeBytesSizeNoTag(list.get(i));
+ }
+ return size;
+ }
+
+ static int computeSizeGroupList(int fieldNumber, List<MessageLite> list) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = 0;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i));
+ }
+ return size;
+ }
+
+ static int computeSizeGroupList(int fieldNumber, List<MessageLite> list, Schema schema) {
+ final int length = list.size();
+ if (length == 0) {
+ return 0;
+ }
+ int size = 0;
+ for (int i = 0; i < length; i++) {
+ size += CodedOutputStream.computeGroupSize(fieldNumber, list.get(i), schema);
+ }
+ return size;
+ }
+
+ /**
+ * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method.
+ *
+ * @see #shouldUseTableSwitch(int, int, int)
+ */
+ public static boolean shouldUseTableSwitch(FieldInfo[] fields) {
+ // Determine whether to issue a tableswitch or a lookupswitch
+ // instruction.
+ if (fields.length == 0) {
+ return false;
+ }
+
+ int lo = fields[0].getFieldNumber();
+ int hi = fields[fields.length - 1].getFieldNumber();
+ return shouldUseTableSwitch(lo, hi, fields.length);
+ }
+
+ /**
+ * Determines whether to issue tableswitch or lookupswitch for the mergeFrom method. This is based
+ * on the <a href=
+ * "http://hg.openjdk.java.net/jdk8/jdk8/langtools/file/30db5e0aaf83/src/share/classes/com/sun/tools/javac/jvm/Gen.java#l1159">
+ * logic in the JDK</a>.
+ *
+ * @param lo the lowest fieldNumber contained within the message.
+ * @param hi the higest fieldNumber contained within the message.
+ * @param numFields the total number of fields in the message.
+ * @return {@code true} if tableswitch should be used, rather than lookupswitch.
+ */
+ public static boolean shouldUseTableSwitch(int lo, int hi, int numFields) {
+ if (hi < DEFAULT_LOOK_UP_START_NUMBER) {
+ return true;
+ }
+ long tableSpaceCost = ((long) hi - lo + 1); // words
+ long tableTimeCost = 3; // comparisons
+ long lookupSpaceCost = 3 + 2 * (long) numFields;
+ long lookupTimeCost = 3 + (long) numFields;
+ return tableSpaceCost + 3 * tableTimeCost <= lookupSpaceCost + 3 * lookupTimeCost;
+ }
+
+ public static UnknownFieldSchema<?, ?> proto2UnknownFieldSetSchema() {
+ return PROTO2_UNKNOWN_FIELD_SET_SCHEMA;
+ }
+
+ public static UnknownFieldSchema<?, ?> proto3UnknownFieldSetSchema() {
+ return PROTO3_UNKNOWN_FIELD_SET_SCHEMA;
+ }
+
+ public static UnknownFieldSchema<?, ?> unknownFieldSetLiteSchema() {
+ return UNKNOWN_FIELD_SET_LITE_SCHEMA;
+ }
+
+ private static UnknownFieldSchema<?, ?> getUnknownFieldSetSchema(boolean proto3) {
+ try {
+ Class<?> clz = getUnknownFieldSetSchemaClass();
+ if (clz == null) {
+ return null;
+ }
+ return (UnknownFieldSchema) clz.getConstructor(boolean.class).newInstance(proto3);
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+
+ private static Class<?> getGeneratedMessageClass() {
+ try {
+ return Class.forName("com.google.protobuf.GeneratedMessageV3");
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ private static Class<?> getUnknownFieldSetSchemaClass() {
+ try {
+ return Class.forName("com.google.protobuf.UnknownFieldSetSchema");
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+ static Object getMapDefaultEntry(Class<?> clazz, String name) {
+ try {
+ Class<?> holder =
+ Class.forName(clazz.getName() + "$" + toCamelCase(name, true) + "DefaultEntryHolder");
+ Field[] fields = holder.getDeclaredFields();
+ if (fields.length != 1) {
+ throw new IllegalStateException(
+ "Unable to look up map field default entry holder class for "
+ + name
+ + " in "
+ + clazz.getName());
+ }
+ return UnsafeUtil.getStaticObject(fields[0]);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ static String toCamelCase(String name, boolean capNext) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < name.length(); ++i) {
+ char c = name.charAt(i);
+ // Matches protoc field name function:
+ if ('a' <= c && c <= 'z') {
+ if (capNext) {
+ sb.append((char) (c + ('A' - 'a')));
+ } else {
+ sb.append(c);
+ }
+ capNext = false;
+ } else if ('A' <= c && c <= 'Z') {
+ if (i == 0 && !capNext) {
+ // Force first letter to lower-case unless explicitly told to capitalize it.
+ sb.append((char) (c - ('A' - 'a')));
+ } else {
+ sb.append(c);
+ }
+ capNext = false;
+ } else if ('0' <= c && c <= '9') {
+ sb.append(c);
+ capNext = true;
+ } else {
+ capNext = true;
+ }
+ }
+ return sb.toString();
+ }
+
+ /** Returns true if both are null or both are {@link Object#equals}. */
+ static boolean safeEquals(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
+ }
+
+ static <T> void mergeMap(MapFieldSchema mapFieldSchema, T message, T o, long offset) {
+ Object merged =
+ mapFieldSchema.mergeFrom(
+ UnsafeUtil.getObject(message, offset), UnsafeUtil.getObject(o, offset));
+ UnsafeUtil.putObject(message, offset, merged);
+ }
+
+ static <T, FT extends FieldDescriptorLite<FT>> void mergeExtensions(
+ ExtensionSchema<FT> schema, T message, T other) {
+ FieldSet<FT> otherExtensions = schema.getExtensions(other);
+ if (!otherExtensions.isEmpty()) {
+ FieldSet<FT> messageExtensions = schema.getMutableExtensions(message);
+ messageExtensions.mergeFrom(otherExtensions);
+ }
+ }
+
+ static <T, UT, UB> void mergeUnknownFields(
+ UnknownFieldSchema<UT, UB> schema, T message, T other) {
+ UT messageUnknowns = schema.getFromMessage(message);
+ UT otherUnknowns = schema.getFromMessage(other);
+ UT merged = schema.merge(messageUnknowns, otherUnknowns);
+ schema.setToMessage(message, merged);
+ }
+
+ /** Filters unrecognized enum values in a list. */
+ static <UT, UB> UB filterUnknownEnumList(
+ int number,
+ List<Integer> enumList,
+ EnumLiteMap<?> enumMap,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema) {
+ if (enumMap == null) {
+ return unknownFields;
+ }
+ // TODO(dweis): Specialize for IntArrayList to avoid boxing.
+ if (enumList instanceof RandomAccess) {
+ int writePos = 0;
+ int size = enumList.size();
+ for (int readPos = 0; readPos < size; ++readPos) {
+ int enumValue = enumList.get(readPos);
+ if (enumMap.findValueByNumber(enumValue) != null) {
+ if (readPos != writePos) {
+ enumList.set(writePos, enumValue);
+ }
+ ++writePos;
+ } else {
+ unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema);
+ }
+ }
+ if (writePos != size) {
+ enumList.subList(writePos, size).clear();
+ }
+ } else {
+ for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) {
+ int enumValue = it.next();
+ if (enumMap.findValueByNumber(enumValue) == null) {
+ unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema);
+ it.remove();
+ }
+ }
+ }
+ return unknownFields;
+ }
+
+ /** Filters unrecognized enum values in a list. */
+ static <UT, UB> UB filterUnknownEnumList(
+ int number,
+ List<Integer> enumList,
+ EnumVerifier enumVerifier,
+ UB unknownFields,
+ UnknownFieldSchema<UT, UB> unknownFieldSchema) {
+ if (enumVerifier == null) {
+ return unknownFields;
+ }
+ // TODO(dweis): Specialize for IntArrayList to avoid boxing.
+ if (enumList instanceof RandomAccess) {
+ int writePos = 0;
+ int size = enumList.size();
+ for (int readPos = 0; readPos < size; ++readPos) {
+ int enumValue = enumList.get(readPos);
+ if (enumVerifier.isInRange(enumValue)) {
+ if (readPos != writePos) {
+ enumList.set(writePos, enumValue);
+ }
+ ++writePos;
+ } else {
+ unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema);
+ }
+ }
+ if (writePos != size) {
+ enumList.subList(writePos, size).clear();
+ }
+ } else {
+ for (Iterator<Integer> it = enumList.iterator(); it.hasNext(); ) {
+ int enumValue = it.next();
+ if (!enumVerifier.isInRange(enumValue)) {
+ unknownFields = storeUnknownEnum(number, enumValue, unknownFields, unknownFieldSchema);
+ it.remove();
+ }
+ }
+ }
+ return unknownFields;
+ }
+
+ /** Stores an unrecognized enum value as an unknown value. */
+ static <UT, UB> UB storeUnknownEnum(
+ int number, int enumValue, UB unknownFields, UnknownFieldSchema<UT, UB> unknownFieldSchema) {
+ if (unknownFields == null) {
+ unknownFields = unknownFieldSchema.newBuilder();
+ }
+ unknownFieldSchema.addVarint(unknownFields, number, enumValue);
+ return unknownFields;
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
index 6bd65d6f4..546e56e85 100644
--- a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
+++ b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -136,6 +136,8 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
// 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;
+ private Map<K, V> overflowEntriesDescending;
+ private volatile DescendingEntrySet lazyDescendingEntrySet;
/**
* @code arraySize Size of the array in which the lexicographically smallest mappings are stored.
@@ -145,6 +147,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
this.maxArraySize = arraySize;
this.entryList = Collections.emptyList();
this.overflowEntries = Collections.emptyMap();
+ this.overflowEntriesDescending = Collections.emptyMap();
}
/** Make this map immutable from this point forward. */
@@ -158,6 +161,10 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
overflowEntries.isEmpty()
? Collections.<K, V>emptyMap()
: Collections.unmodifiableMap(overflowEntries);
+ overflowEntriesDescending =
+ overflowEntriesDescending.isEmpty()
+ ? Collections.<K, V>emptyMap()
+ : Collections.unmodifiableMap(overflowEntriesDescending);
isImmutable = true;
}
}
@@ -189,6 +196,11 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
: overflowEntries.entrySet();
}
+ Iterable<Map.Entry<K, V>> getOverflowEntriesDescending() {
+ return overflowEntriesDescending.isEmpty()
+ ? EmptySet.<Map.Entry<K, V>>iterable()
+ : overflowEntriesDescending.entrySet();
+ }
@Override
public int size() {
@@ -344,6 +356,12 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
return lazyEntrySet;
}
+ Set<Map.Entry<K, V>> descendingEntrySet() {
+ if (lazyDescendingEntrySet == null) {
+ lazyDescendingEntrySet = new DescendingEntrySet();
+ }
+ return lazyDescendingEntrySet;
+ }
/** @throws UnsupportedOperationException if {@link #makeImmutable()} has has been called. */
private void checkMutable() {
@@ -361,6 +379,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
checkMutable();
if (overflowEntries.isEmpty() && !(overflowEntries instanceof TreeMap)) {
overflowEntries = new TreeMap<K, V>();
+ overflowEntriesDescending = ((TreeMap<K, V>) overflowEntries).descendingMap();
}
return (SortedMap<K, V>) overflowEntries;
}
@@ -501,6 +520,12 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
}
}
+ private class DescendingEntrySet extends EntrySet {
+ @Override
+ public Iterator<java.util.Map.Entry<K, V>> iterator() {
+ return new DescendingEntryIterator();
+ }
+ }
/**
* Iterator implementation that switches from the entry array to the overflow entries
@@ -558,6 +583,46 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
}
/**
+ * Reverse Iterator implementation that switches from the entry array to the overflow entries
+ * appropriately.
+ */
+ private class DescendingEntryIterator implements Iterator<Map.Entry<K, V>> {
+
+ private int pos = entryList.size();
+ private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
+
+ @Override
+ public boolean hasNext() {
+ return (pos > 0 && pos <= entryList.size()) || getOverflowIterator().hasNext();
+ }
+
+ @Override
+ public Map.Entry<K, V> next() {
+ if (getOverflowIterator().hasNext()) {
+ return getOverflowIterator().next();
+ }
+ return entryList.get(--pos);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * 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 = overflowEntriesDescending.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.
diff --git a/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java b/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java
new file mode 100755
index 000000000..a32b1430e
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java
@@ -0,0 +1,167 @@
+// 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.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Information for the layout of a protobuf message class. This describes all of the fields
+ * contained within a message.
+ */
+@ExperimentalApi
+final class StructuralMessageInfo implements MessageInfo {
+ private final ProtoSyntax syntax;
+ private final boolean messageSetWireFormat;
+ private final int[] checkInitialized;
+ private final FieldInfo[] fields;
+ private final MessageLite defaultInstance;
+
+ /**
+ * Constructor.
+ *
+ * @param checkInitialized fields to check in isInitialized().
+ * @param fields the set of fields for the message, in field number order.
+ */
+ StructuralMessageInfo(
+ ProtoSyntax syntax,
+ boolean messageSetWireFormat,
+ int[] checkInitialized,
+ FieldInfo[] fields,
+ Object defaultInstance) {
+ this.syntax = syntax;
+ this.messageSetWireFormat = messageSetWireFormat;
+ this.checkInitialized = checkInitialized;
+ this.fields = fields;
+ this.defaultInstance = (MessageLite) checkNotNull(defaultInstance, "defaultInstance");
+ }
+
+ /** Gets the syntax for the message (e.g. PROTO2, PROTO3). */
+ @Override
+ public ProtoSyntax getSyntax() {
+ return syntax;
+ }
+
+ /** Indicates whether or not the message should be represented with message set wire format. */
+ @Override
+ public boolean isMessageSetWireFormat() {
+ return messageSetWireFormat;
+ }
+
+ /** An array of field numbers that need to be checked for isInitialized(). */
+ public int[] getCheckInitialized() {
+ return checkInitialized;
+ }
+
+ /**
+ * Gets the information for all fields within this message, sorted in ascending order by their
+ * field number.
+ */
+ public FieldInfo[] getFields() {
+ return fields;
+ }
+
+ @Override
+ public MessageLite getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ /** Helper method for creating a new builder for {@link MessageInfo}. */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /** Helper method for creating a new builder for {@link MessageInfo}. */
+ public static Builder newBuilder(int numFields) {
+ return new Builder(numFields);
+ }
+
+ /** A builder of {@link MessageInfo} instances. */
+ public static final class Builder {
+ private final List<FieldInfo> fields;
+ private ProtoSyntax syntax;
+ private boolean wasBuilt;
+ private boolean messageSetWireFormat;
+ private int[] checkInitialized = null;
+ private Object defaultInstance;
+
+ public Builder() {
+ fields = new ArrayList<FieldInfo>();
+ }
+
+ public Builder(int numFields) {
+ fields = new ArrayList<FieldInfo>(numFields);
+ }
+
+ public void withDefaultInstance(Object defaultInstance) {
+ this.defaultInstance = defaultInstance;
+ }
+
+ public void withSyntax(ProtoSyntax syntax) {
+ this.syntax = checkNotNull(syntax, "syntax");
+ }
+
+ public void withMessageSetWireFormat(boolean messageSetWireFormat) {
+ this.messageSetWireFormat = messageSetWireFormat;
+ }
+
+ public void withCheckInitialized(int[] checkInitialized) {
+ this.checkInitialized = checkInitialized;
+ }
+
+ public void withField(FieldInfo field) {
+ if (wasBuilt) {
+ throw new IllegalStateException("Builder can only build once");
+ }
+ fields.add(field);
+ }
+
+ public StructuralMessageInfo build() {
+ if (wasBuilt) {
+ throw new IllegalStateException("Builder can only build once");
+ }
+ if (syntax == null) {
+ throw new IllegalStateException("Must specify a proto syntax");
+ }
+ wasBuilt = true;
+ Collections.sort(fields);
+ return new StructuralMessageInfo(
+ syntax,
+ messageSetWireFormat,
+ checkInitialized,
+ fields.toArray(new FieldInfo[0]),
+ defaultInstance);
+ }
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index f00c812fc..2326a05ff 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -1247,6 +1247,18 @@ public final class TextFormat {
SingularOverwritePolicy.ALLOW_SINGULAR_OVERWRITES;
private TextFormatParseInfoTree.Builder parseInfoTreeBuilder = null;
+ /**
+ * Set whether this parser will allow unknown fields. By default, an exception is thrown if an
+ * unknown field is encountered. If this is set, the parser will only log a warning. Allow
+ * unknown fields will also allow unknown extensions.
+ *
+ * <p>Use of this parameter is discouraged which may hide some errors (e.g.
+ * spelling error on field name).
+ */
+ public Builder setAllowUnknownFields(boolean allowUnknownFields) {
+ this.allowUnknownFields = allowUnknownFields;
+ return this;
+ }
/**
* Set whether this parser will allow unknown extensions. By default, an
@@ -1448,14 +1460,15 @@ public final class TextFormat {
extension = target.findExtensionByName(extensionRegistry, name.toString());
if (extension == null) {
- String message = (tokenizer.getPreviousLine() + 1)
- + ":"
- + (tokenizer.getPreviousColumn() + 1)
- + ":\t"
- + type.getFullName()
- + ".["
- + name
- + "]";
+ String message =
+ (tokenizer.getPreviousLine() + 1)
+ + ":"
+ + (tokenizer.getPreviousColumn() + 1)
+ + ":\t"
+ + type.getFullName()
+ + ".["
+ + name
+ + "]";
unknownFields.add(new UnknownField(message, UnknownField.Type.EXTENSION));
} else {
if (extension.descriptor.getContainingType() != type) {
@@ -1653,24 +1666,18 @@ public final class TextFormat {
endToken = "}";
}
- Message defaultInstance = (extension == null) ? null : extension.defaultInstance;
- MessageReflection.MergeTarget subField =
- target.newMergeTargetForField(field, defaultInstance);
+ Message defaultInstance = (extension == null) ? null : extension.defaultInstance;
+ MessageReflection.MergeTarget subField =
+ target.newMergeTargetForField(field, defaultInstance);
- while (!tokenizer.tryConsume(endToken)) {
- if (tokenizer.atEnd()) {
- throw tokenizer.parseException("Expected \"" + endToken + "\".");
+ while (!tokenizer.tryConsume(endToken)) {
+ if (tokenizer.atEnd()) {
+ throw tokenizer.parseException("Expected \"" + endToken + "\".");
+ }
+ mergeField(tokenizer, extensionRegistry, subField, parseTreeBuilder, unknownFields);
}
- mergeField(
- tokenizer,
- extensionRegistry,
- subField,
- parseTreeBuilder,
- unknownFields);
- }
-
- value = subField.finish();
+ value = subField.finish();
} else {
switch (field.getType()) {
case INT32:
@@ -1776,6 +1783,7 @@ public final class TextFormat {
}
}
+
/** Skips the next field including the field's name and value. */
private void skipField(Tokenizer tokenizer) throws ParseException {
if (tokenizer.tryConsume("[")) {
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
new file mode 100755
index 000000000..e736d5ce9
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
@@ -0,0 +1,133 @@
+// 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;
+
+@ExperimentalApi
+abstract class UnknownFieldSchema<T, B> {
+
+ /** Whether unknown fields should be dropped. */
+ abstract boolean shouldDiscardUnknownFields(Reader reader);
+
+ /** Adds a varint value to the unknown fields. */
+ abstract void addVarint(B fields, int number, long value);
+
+ /** Adds a fixed32 value to the unknown fields. */
+ abstract void addFixed32(B fields, int number, int value);
+
+ /** Adds a fixed64 value to the unknown fields. */
+ abstract void addFixed64(B fields, int number, long value);
+
+ /** Adds a length delimited value to the unknown fields. */
+ abstract void addLengthDelimited(B fields, int number, ByteString value);
+
+ /** Adds a group value to the unknown fields. */
+ abstract void addGroup(B fields, int number, T subFieldSet);
+
+ /** Create a new builder for unknown fields. */
+ abstract B newBuilder();
+
+ /** Returns an immutable instance of the field container. */
+ abstract T toImmutable(B fields);
+
+ /**
+ * Sets the unknown fields into the message. Caller must take care of the mutability of the
+ * fields.
+ */
+ abstract void setToMessage(Object message, T fields);
+
+ /** Get the unknown fields from the message. */
+ abstract T getFromMessage(Object message);
+
+ /** Returns a builder for unknown fields in the message. */
+ abstract B getBuilderFromMessage(Object message);
+
+ /** Sets an unknown field builder into the message. */
+ abstract void setBuilderToMessage(Object message, B builder);
+
+ /** Marks unknown fields as immutable. */
+ abstract void makeImmutable(Object message);
+
+ /** Merges one field into the unknown fields. */
+ final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException {
+ int tag = reader.getTag();
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ addVarint(unknownFields, fieldNumber, reader.readInt64());
+ return true;
+ case WireFormat.WIRETYPE_FIXED32:
+ addFixed32(unknownFields, fieldNumber, reader.readFixed32());
+ return true;
+ case WireFormat.WIRETYPE_FIXED64:
+ addFixed64(unknownFields, fieldNumber, reader.readFixed64());
+ return true;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ addLengthDelimited(unknownFields, fieldNumber, reader.readBytes());
+ return true;
+ case WireFormat.WIRETYPE_START_GROUP:
+ final B subFields = newBuilder();
+ int endGroupTag = WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
+ mergeFrom(subFields, reader);
+ if (endGroupTag != reader.getTag()) {
+ throw InvalidProtocolBufferException.invalidEndTag();
+ }
+ addGroup(unknownFields, fieldNumber, toImmutable(subFields));
+ return true;
+ case WireFormat.WIRETYPE_END_GROUP:
+ return false;
+ default:
+ throw InvalidProtocolBufferException.invalidWireType();
+ }
+ }
+
+ final void mergeFrom(B unknownFields, Reader reader) throws IOException {
+ while (true) {
+ if (reader.getFieldNumber() == Reader.READ_DONE
+ || !mergeOneFieldFrom(unknownFields, reader)) {
+ break;
+ }
+ }
+ }
+
+ abstract void writeTo(T unknownFields, Writer writer) throws IOException;
+
+ abstract void writeAsMessageSetTo(T unknownFields, Writer writer) throws IOException;
+
+ /** Merges {@code source} into {@code destination} and returns the merged instance. */
+ abstract T merge(T destination, T source);
+
+ /** Get the serialized size for message set serialization. */
+ abstract int getSerializedSizeAsMessageSet(T message);
+
+ abstract int getSerializedSize(T unknowns);
+}
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 39deec048..bde1303db 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -59,6 +59,7 @@ public final class UnknownFieldSet implements MessageLite {
private UnknownFieldSet() {
fields = null;
+ fieldsDescending = null;
}
/** Create a new {@link Builder}. */
@@ -90,10 +91,14 @@ public final class UnknownFieldSet implements MessageLite {
*/
UnknownFieldSet(final Map<Integer, Field> fields, final Map<Integer, Field> fieldsDescending) {
this.fields = fields;
+ this.fieldsDescending = fieldsDescending;
}
private final Map<Integer, Field> fields;
+ /** A copy of {@link #fields} who's iterator order is reversed. */
+ private final Map<Integer, Field> fieldsDescending;
+
@Override
public boolean equals(final Object other) {
@@ -212,6 +217,35 @@ public final class UnknownFieldSet implements MessageLite {
}
}
+ /** Serializes the set and writes it to {@code writer}. */
+ void writeTo(Writer writer) throws IOException {
+ if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
+ // Write fields in descending order.
+ for (Map.Entry<Integer, Field> entry : fieldsDescending.entrySet()) {
+ entry.getValue().writeTo(entry.getKey(), writer);
+ }
+ } else {
+ // Write fields in ascending order.
+ for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ entry.getValue().writeTo(entry.getKey(), writer);
+ }
+ }
+ }
+
+ /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */
+ void writeAsMessageSetTo(final Writer writer) throws IOException {
+ if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
+ // Write fields in descending order.
+ for (final Map.Entry<Integer, Field> entry : fieldsDescending.entrySet()) {
+ entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer);
+ }
+ } else {
+ // Write fields in ascending order.
+ for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
+ entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), writer);
+ }
+ }
+ }
/** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */
public int getSerializedSizeAsMessageSet() {
@@ -328,6 +362,8 @@ public final class UnknownFieldSet implements MessageLite {
result = getDefaultInstance();
} else {
Map<Integer, Field> descendingFields = null;
+ descendingFields =
+ Collections.unmodifiableMap(((TreeMap<Integer, Field>) fields).descendingMap());
result = new UnknownFieldSet(Collections.unmodifiableMap(fields), descendingFields);
}
fields = null;
@@ -344,6 +380,8 @@ public final class UnknownFieldSet implements MessageLite {
public Builder clone() {
getFieldBuilder(0); // Force lastField to be built.
Map<Integer, Field> descendingFields = null;
+ descendingFields =
+ Collections.unmodifiableMap(((TreeMap<Integer, Field>) fields).descendingMap());
return UnknownFieldSet.newBuilder().mergeFrom(new UnknownFieldSet(fields, descendingFields));
}
@@ -808,6 +846,47 @@ public final class UnknownFieldSet implements MessageLite {
}
}
+ /** Serializes the field, including field number, and writes it to {@code writer}. */
+ void writeTo(final int fieldNumber, final Writer writer) throws IOException {
+ writer.writeInt64List(fieldNumber, varint, false);
+ writer.writeFixed32List(fieldNumber, fixed32, false);
+ writer.writeFixed64List(fieldNumber, fixed64, false);
+ writer.writeBytesList(fieldNumber, lengthDelimited);
+
+ if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) {
+ for (int i = 0; i < group.size(); i++) {
+ writer.writeStartGroup(fieldNumber);
+ group.get(i).writeTo(writer);
+ writer.writeEndGroup(fieldNumber);
+ }
+ } else {
+ for (int i = group.size() - 1; i >= 0; i--) {
+ writer.writeEndGroup(fieldNumber);
+ group.get(i).writeTo(writer);
+ writer.writeStartGroup(fieldNumber);
+ }
+ }
+ }
+
+ /**
+ * Serializes the field, including field number, and writes it to {@code writer}, using {@code
+ * MessageSet} wire format.
+ */
+ private void writeAsMessageSetExtensionTo(final int fieldNumber, final Writer writer)
+ throws IOException {
+ if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
+ // Write in descending field order.
+ ListIterator<ByteString> iter = lengthDelimited.listIterator(lengthDelimited.size());
+ while (iter.hasPrevious()) {
+ writer.writeMessageSetItem(fieldNumber, iter.previous());
+ }
+ } else {
+ // Write in ascending field order.
+ for (final ByteString value : lengthDelimited) {
+ writer.writeMessageSetItem(fieldNumber, value);
+ }
+ }
+ }
/**
* Get the number of bytes required to encode this field, including field number, using {@code
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
index 7c5ec6e98..2f6315c80 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java
@@ -168,6 +168,72 @@ public final class UnknownFieldSetLite {
}
}
+ /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */
+ void writeAsMessageSetTo(Writer writer) throws IOException {
+ if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
+ // Write fields in descending order.
+ for (int i = count - 1; i >= 0; i--) {
+ int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
+ writer.writeMessageSetItem(fieldNumber, objects[i]);
+ }
+ } else {
+ // Write fields in ascending order.
+ for (int i = 0; i < count; i++) {
+ int fieldNumber = WireFormat.getTagFieldNumber(tags[i]);
+ writer.writeMessageSetItem(fieldNumber, objects[i]);
+ }
+ }
+ }
+
+ /** Serializes the set and writes it to {@code writer}. */
+ public void writeTo(Writer writer) throws IOException {
+ if (count == 0) {
+ return;
+ }
+
+ // TODO: tags are not sorted, so there's no write order guarantees
+ if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) {
+ for (int i = 0; i < count; ++i) {
+ writeField(tags[i], objects[i], writer);
+ }
+ } else {
+ for (int i = count - 1; i >= 0; --i) {
+ writeField(tags[i], objects[i], writer);
+ }
+ }
+ }
+
+ private static void writeField(int tag, Object object, Writer writer) throws IOException {
+ int fieldNumber = WireFormat.getTagFieldNumber(tag);
+ switch (WireFormat.getTagWireType(tag)) {
+ case WireFormat.WIRETYPE_VARINT:
+ writer.writeInt64(fieldNumber, (Long) object);
+ break;
+ case WireFormat.WIRETYPE_FIXED32:
+ writer.writeFixed32(fieldNumber, (Integer) object);
+ break;
+ case WireFormat.WIRETYPE_FIXED64:
+ writer.writeFixed64(fieldNumber, (Long) object);
+ break;
+ case WireFormat.WIRETYPE_LENGTH_DELIMITED:
+ writer.writeBytes(fieldNumber, (ByteString) object);
+ break;
+ case WireFormat.WIRETYPE_START_GROUP:
+ if (writer.fieldOrder() == Writer.FieldOrder.ASCENDING) {
+ writer.writeStartGroup(fieldNumber);
+ ((UnknownFieldSetLite) object).writeTo(writer);
+ writer.writeEndGroup(fieldNumber);
+ } else {
+ writer.writeEndGroup(fieldNumber);
+ ((UnknownFieldSetLite) object).writeTo(writer);
+ writer.writeStartGroup(fieldNumber);
+ }
+ break;
+ default:
+ // TODO(liujisi): Change writeTo to throw IOException?
+ throw new RuntimeException(InvalidProtocolBufferException.invalidWireType());
+ }
+ }
/**
* Get the number of bytes required to encode this field, including field number, using {@code
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java
new file mode 100755
index 000000000..ffd723230
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java
@@ -0,0 +1,140 @@
+// 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;
+
+class UnknownFieldSetLiteSchema
+ extends UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> {
+
+ UnknownFieldSetLiteSchema() {}
+
+ @Override
+ boolean shouldDiscardUnknownFields(Reader reader) {
+ // We never drop unknown fields in lite.
+ return false;
+ }
+
+ @Override
+ UnknownFieldSetLite newBuilder() {
+ return UnknownFieldSetLite.newInstance();
+ }
+
+ @Override
+ void addVarint(UnknownFieldSetLite fields, int number, long value) {
+ fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_VARINT), value);
+ }
+
+ @Override
+ void addFixed32(UnknownFieldSetLite fields, int number, int value) {
+ fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_FIXED32), value);
+ }
+
+ @Override
+ void addFixed64(UnknownFieldSetLite fields, int number, long value) {
+ fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_FIXED64), value);
+ }
+
+ @Override
+ void addLengthDelimited(UnknownFieldSetLite fields, int number, ByteString value) {
+ fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED), value);
+ }
+
+ @Override
+ void addGroup(UnknownFieldSetLite fields, int number, UnknownFieldSetLite subFieldSet) {
+ fields.storeField(WireFormat.makeTag(number, WireFormat.WIRETYPE_START_GROUP), subFieldSet);
+ }
+
+ @Override
+ UnknownFieldSetLite toImmutable(UnknownFieldSetLite fields) {
+ fields.makeImmutable();
+ return fields;
+ }
+
+ @Override
+ void setToMessage(Object message, UnknownFieldSetLite fields) {
+ ((GeneratedMessageLite<?, ?>) message).unknownFields = fields;
+ }
+
+ @Override
+ UnknownFieldSetLite getFromMessage(Object message) {
+ return ((GeneratedMessageLite<?, ?>) message).unknownFields;
+ }
+
+ @Override
+ UnknownFieldSetLite getBuilderFromMessage(Object message) {
+ UnknownFieldSetLite unknownFields = getFromMessage(message);
+ // When parsing into a lite message object, its UnknownFieldSet is either the default instance
+ // or mutable. It can't be in a state where it's immutable but not default instance.
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
+ unknownFields = UnknownFieldSetLite.newInstance();
+ setToMessage(message, unknownFields);
+ }
+ return unknownFields;
+ }
+
+ @Override
+ void setBuilderToMessage(Object message, UnknownFieldSetLite fields) {
+ setToMessage(message, fields);
+ }
+
+ @Override
+ void makeImmutable(Object message) {
+ getFromMessage(message).makeImmutable();
+ }
+
+ @Override
+ void writeTo(UnknownFieldSetLite fields, Writer writer) throws IOException {
+ fields.writeTo(writer);
+ }
+
+ @Override
+ void writeAsMessageSetTo(UnknownFieldSetLite fields, Writer writer) throws IOException {
+ fields.writeAsMessageSetTo(writer);
+ }
+
+ @Override
+ UnknownFieldSetLite merge(UnknownFieldSetLite message, UnknownFieldSetLite other) {
+ return other.equals(UnknownFieldSetLite.getDefaultInstance())
+ ? message
+ : UnknownFieldSetLite.mutableCopyOf(message, other);
+ }
+
+ @Override
+ int getSerializedSize(UnknownFieldSetLite unknowns) {
+ return unknowns.getSerializedSize();
+ }
+
+ @Override
+ int getSerializedSizeAsMessageSet(UnknownFieldSetLite unknowns) {
+ return unknowns.getSerializedSizeAsMessageSet();
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java
new file mode 100755
index 000000000..b838c4b54
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java
@@ -0,0 +1,132 @@
+// 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;
+
+class UnknownFieldSetSchema extends UnknownFieldSchema<UnknownFieldSet, UnknownFieldSet.Builder> {
+
+ private final boolean proto3;
+
+ public UnknownFieldSetSchema(boolean proto3) {
+ this.proto3 = proto3;
+ }
+
+ @Override
+ boolean shouldDiscardUnknownFields(Reader reader) {
+ return reader.shouldDiscardUnknownFields();
+ }
+
+ @Override
+ UnknownFieldSet.Builder newBuilder() {
+ return UnknownFieldSet.newBuilder();
+ }
+
+ @Override
+ void addVarint(UnknownFieldSet.Builder fields, int number, long value) {
+ fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addVarint(value).build());
+ }
+
+ @Override
+ void addFixed32(UnknownFieldSet.Builder fields, int number, int value) {
+ fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addFixed32(value).build());
+ }
+
+ @Override
+ void addFixed64(UnknownFieldSet.Builder fields, int number, long value) {
+ fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addFixed64(value).build());
+ }
+
+ @Override
+ void addLengthDelimited(UnknownFieldSet.Builder fields, int number, ByteString value) {
+ fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addLengthDelimited(value).build());
+ }
+
+ @Override
+ void addGroup(UnknownFieldSet.Builder fields, int number, UnknownFieldSet subFieldSet) {
+ fields.mergeField(number, UnknownFieldSet.Field.newBuilder().addGroup(subFieldSet).build());
+ }
+
+ @Override
+ UnknownFieldSet toImmutable(UnknownFieldSet.Builder fields) {
+ return fields.build();
+ }
+
+ @Override
+ void writeTo(UnknownFieldSet message, Writer writer) throws IOException {
+ message.writeTo(writer);
+ }
+
+ @Override
+ void writeAsMessageSetTo(UnknownFieldSet message, Writer writer) throws IOException {
+ message.writeAsMessageSetTo(writer);
+ }
+
+ @Override
+ UnknownFieldSet getFromMessage(Object message) {
+ return ((GeneratedMessageV3) message).unknownFields;
+ }
+
+ @Override
+ void setToMessage(Object message, UnknownFieldSet fields) {
+ ((GeneratedMessageV3) message).unknownFields = fields;
+ }
+
+ @Override
+ UnknownFieldSet.Builder getBuilderFromMessage(Object message) {
+ return ((GeneratedMessageV3) message).unknownFields.toBuilder();
+ }
+
+ @Override
+ void setBuilderToMessage(Object message, UnknownFieldSet.Builder builder) {
+ ((GeneratedMessageV3) message).unknownFields = builder.build();
+ }
+
+ @Override
+ void makeImmutable(Object message) {
+ // Already immutable.
+ }
+
+ @Override
+ UnknownFieldSet merge(UnknownFieldSet message, UnknownFieldSet other) {
+ return message.toBuilder().mergeFrom(other).build();
+ }
+
+ @Override
+ int getSerializedSize(UnknownFieldSet message) {
+ return message.getSerializedSize();
+ }
+
+ @Override
+ int getSerializedSizeAsMessageSet(UnknownFieldSet unknowns) {
+ return unknowns.getSerializedSizeAsMessageSet();
+ }
+}
diff --git a/java/core/src/main/java/com/google/protobuf/Writer.java b/java/core/src/main/java/com/google/protobuf/Writer.java
new file mode 100755
index 000000000..3f95c325d
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/Writer.java
@@ -0,0 +1,219 @@
+// 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.List;
+import java.util.Map;
+
+/** A writer that performs serialization of protobuf message fields. */
+@ExperimentalApi
+interface Writer {
+
+ /** The order in which the fields are written by a {@link Writer}. */
+ enum FieldOrder {
+ /** Fields are written in ascending order by field number. */
+ ASCENDING,
+
+ /** Fields are written in descending order by field number. */
+ DESCENDING
+ }
+
+ /** Indicates the order in which the fields are written by this {@link Writer}. */
+ FieldOrder fieldOrder();
+
+ /** Writes a field of type {@link FieldType#SFIXED32}. */
+ void writeSFixed32(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#INT64}. */
+ void writeInt64(int fieldNumber, long value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#SFIXED64}. */
+ void writeSFixed64(int fieldNumber, long value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#FLOAT}. */
+ void writeFloat(int fieldNumber, float value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#DOUBLE}. */
+ void writeDouble(int fieldNumber, double value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#ENUM}. */
+ void writeEnum(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#UINT64}. */
+ void writeUInt64(int fieldNumber, long value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#INT32}. */
+ void writeInt32(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#FIXED64}. */
+ void writeFixed64(int fieldNumber, long value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#FIXED32}. */
+ void writeFixed32(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#BOOL}. */
+ void writeBool(int fieldNumber, boolean value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#STRING}. */
+ void writeString(int fieldNumber, String value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#BYTES}. */
+ void writeBytes(int fieldNumber, ByteString value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#UINT32}. */
+ void writeUInt32(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#SINT32}. */
+ void writeSInt32(int fieldNumber, int value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#SINT64}. */
+ void writeSInt64(int fieldNumber, long value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#MESSAGE}. */
+ void writeMessage(int fieldNumber, Object value) throws IOException;
+
+ /** Writes a field of type {@link FieldType#MESSAGE}. */
+ void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException;
+
+ /**
+ * Writes a field of type {@link FieldType#GROUP}.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeGroup(int fieldNumber, Object value) throws IOException;
+
+ /**
+ * Writes a field of type {@link FieldType#GROUP}.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException;
+
+ /**
+ * Writes a single start group tag.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeStartGroup(int fieldNumber) throws IOException;
+
+ /**
+ * Writes a single end group tag.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeEndGroup(int fieldNumber) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#INT32}. */
+ void writeInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#FIXED32}. */
+ void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#INT64}. */
+ void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#UINT64}. */
+ void writeUInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#FIXED64}. */
+ void writeFixed64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#FLOAT}. */
+ void writeFloatList(int fieldNumber, List<Float> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#DOUBLE}. */
+ void writeDoubleList(int fieldNumber, List<Double> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#ENUM}. */
+ void writeEnumList(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#BOOL}. */
+ void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#STRING}. */
+ void writeStringList(int fieldNumber, List<String> value) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#BYTES}. */
+ void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#UINT32}. */
+ void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#SFIXED32}. */
+ void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#SFIXED64}. */
+ void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#SINT32}. */
+ void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#SINT64}. */
+ void writeSInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#MESSAGE}. */
+ void writeMessageList(int fieldNumber, List<?> value) throws IOException;
+
+ /** Writes a list field of type {@link FieldType#MESSAGE}. */
+ void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException;
+
+ /**
+ * Writes a list field of type {@link FieldType#GROUP}.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeGroupList(int fieldNumber, List<?> value) throws IOException;
+
+ /**
+ * Writes a list field of type {@link FieldType#GROUP}.
+ *
+ * @deprecated groups fields are deprecated.
+ */
+ @Deprecated
+ void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException;
+
+ /**
+ * Writes a message field in {@code MessageSet} wire-format.
+ *
+ * @param value A message instance or an opaque {@link ByteString} for an unknown field.
+ */
+ void writeMessageSetItem(int fieldNumber, Object value) throws IOException;
+
+ /** Writes a map field. */
+ <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
+ throws IOException;
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java
new file mode 100755
index 000000000..5d3fd3bd6
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java
@@ -0,0 +1,199 @@
+// 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.assertNull;
+
+import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.TestEnum;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import org.junit.Test;
+
+/** Base class for tests using {@link Proto2MessageLite}. */
+public abstract class AbstractProto2LiteSchemaTest extends AbstractSchemaTest<Proto2MessageLite> {
+
+ @Override
+ protected Proto2MessageLiteFactory messageFactory() {
+ return new Proto2MessageLiteFactory(10, 20, 2, 2);
+ }
+
+ @Test
+ public void mergeOptionalMessageFields() throws Exception {
+ Proto2MessageLite message1 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build())
+ .build();
+ Proto2MessageLite message2 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build())
+ .build();
+ Proto2MessageLite message3 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build())
+ .build();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ message1.writeTo(output);
+ message2.writeTo(output);
+ message3.writeTo(output);
+ byte[] data = output.toByteArray();
+
+ Proto2MessageLite merged =
+ ExperimentalSerializationUtil.fromByteArray(data, Proto2MessageLite.class);
+ assertEquals(789, merged.getFieldMessage10().getFieldInt643());
+ assertEquals(456, merged.getFieldMessage10().getFieldInt325());
+ }
+
+ @Test
+ public void oneofFieldsShouldRoundtrip() throws IOException {
+ roundtrip("Field 53", newBuilder().setFieldDouble53(100).build());
+ roundtrip("Field 54", newBuilder().setFieldFloat54(100).build());
+ roundtrip("Field 55", newBuilder().setFieldInt6455(100).build());
+ roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build());
+ roundtrip("Field 57", newBuilder().setFieldInt3257(100).build());
+ roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build());
+ roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build());
+ roundtrip("Field 60", newBuilder().setFieldBool60(true).build());
+ roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build());
+ roundtrip(
+ "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build());
+ roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build());
+ roundtrip("Field 64", newBuilder().setFieldUint3264(100).build());
+ roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build());
+ roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build());
+ roundtrip("Field 67", newBuilder().setFieldSint3267(100).build());
+ roundtrip("Field 68", newBuilder().setFieldSint6468(100).build());
+ roundtrip(
+ "Field 69",
+ newBuilder()
+ .setFieldGroup69(
+ Proto2MessageLite.FieldGroup69.newBuilder().setFieldInt3270(data().getInt()))
+ .build());
+ }
+
+ private Proto2MessageLite.Builder newBuilder() {
+ return messageFactory().newMessage().toBuilder();
+ }
+
+ @Override
+ protected List<Proto2MessageLite> newMessagesMissingRequiredFields() {
+ return messageFactory().newMessagesMissingRequiredFields();
+ }
+
+ @Test
+ public void mapsShouldRoundtrip() throws IOException {
+ roundtrip(
+ "Proto2MessageLiteWithMaps",
+ new Proto2MessageLiteFactory(2, 10, 2, 2).newMessageWithMaps(),
+ Protobuf.getInstance().schemaFor(Proto2MessageLiteWithMaps.class));
+ }
+
+ @Test
+ public void unknownFieldsUnrecognized() throws Exception {
+ Proto2MessageLite expectedMessage = messageFactory().newMessage();
+ byte[] serializedBytes = expectedMessage.toByteArray();
+ Proto2EmptyLite empty =
+ ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2EmptyLite.class);
+
+ // Merge serialized bytes into an empty message, then reserialize and merge it to a new
+ // Proto2Message. Make sure the two messages equal.
+ byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty);
+ Proto2MessageLite roundtripMessage =
+ ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2MessageLite.class);
+ assertEquals(expectedMessage, roundtripMessage);
+ }
+
+ @Test
+ public void unknownEnum() throws IOException {
+ // Use unknown fields to hold invalid enum values.
+ UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance();
+ final int outOfRange = 1000;
+ assertNull(TestEnum.forNumber(outOfRange));
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2MessageLite.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.ONE_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2MessageLite.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.TWO_VALUE);
+
+ {
+ // Construct a packed enum list.
+ int packedSize =
+ CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE)
+ + CodedOutputStream.computeUInt32SizeNoTag(outOfRange)
+ + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE);
+ ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize);
+ CodedOutputStream packedOut = packedBuilder.getCodedOutput();
+ packedOut.writeEnumNoTag(TestEnum.ONE_VALUE);
+ packedOut.writeEnumNoTag(outOfRange);
+ packedOut.writeEnumNoTag(TestEnum.TWO_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2MessageLite.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER,
+ WireFormat.WIRETYPE_LENGTH_DELIMITED),
+ packedBuilder.build());
+ }
+ int size = unknowns.getSerializedSize();
+ byte[] output = new byte[size];
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ unknowns.writeTo(codedOutput);
+ codedOutput.flush();
+
+ Proto2MessageLite parsed =
+ ExperimentalSerializationUtil.fromByteArray(output, Proto2MessageLite.class);
+ assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13());
+ assertEquals(
+ "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count());
+ assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0));
+ assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1));
+ assertEquals(
+ "out-of-range packed repeated enum should not be in message",
+ 2,
+ parsed.getFieldEnumListPacked44Count());
+ assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0));
+ assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java
new file mode 100755
index 000000000..0c1681866
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
+import com.google.protobuf.testing.Proto2Testing.Proto2Empty;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.List;
+import org.junit.Test;
+
+/** Base class for tests using {@link Proto2Message}. */
+public abstract class AbstractProto2SchemaTest extends AbstractSchemaTest<Proto2Message> {
+
+ @Override
+ protected Proto2MessageFactory messageFactory() {
+ return new Proto2MessageFactory(10, 20, 2, 2);
+ }
+
+ @Test
+ public void mergeOptionalMessageFields() throws Exception {
+ Proto2Message message1 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build())
+ .build();
+ Proto2Message message2 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build())
+ .build();
+ Proto2Message message3 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build())
+ .build();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ message1.writeTo(output);
+ message2.writeTo(output);
+ message3.writeTo(output);
+ byte[] data = output.toByteArray();
+
+ Proto2Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto2Message.class);
+ assertEquals(789, merged.getFieldMessage10().getFieldInt643());
+ assertEquals(456, merged.getFieldMessage10().getFieldInt325());
+ }
+
+ @Test
+ public void oneofFieldsShouldRoundtrip() throws IOException {
+ roundtrip("Field 53", newBuilder().setFieldDouble53(100).build());
+ roundtrip("Field 54", newBuilder().setFieldFloat54(100).build());
+ roundtrip("Field 55", newBuilder().setFieldInt6455(100).build());
+ roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build());
+ roundtrip("Field 57", newBuilder().setFieldInt3257(100).build());
+ roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build());
+ roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build());
+ roundtrip("Field 60", newBuilder().setFieldBool60(true).build());
+ roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build());
+ roundtrip(
+ "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build());
+ roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build());
+ roundtrip("Field 64", newBuilder().setFieldUint3264(100).build());
+ roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build());
+ roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build());
+ roundtrip("Field 67", newBuilder().setFieldSint3267(100).build());
+ roundtrip("Field 68", newBuilder().setFieldSint6468(100).build());
+ roundtrip(
+ "Field 69",
+ newBuilder()
+ .setFieldGroup69(
+ Proto2Message.FieldGroup69.newBuilder().setFieldInt3270(data().getInt()))
+ .build());
+ }
+
+ private Proto2Message.Builder newBuilder() {
+ return messageFactory().newMessage().toBuilder();
+ }
+
+ @Test
+ public void mapsShouldRoundtrip() throws IOException {
+ roundtrip(
+ "Proto2MessageWithMaps",
+ new Proto2MessageFactory(2, 10, 2, 2).newMessageWithMaps(),
+ Protobuf.getInstance().schemaFor(Proto2MessageWithMaps.class));
+ }
+
+ @Test
+ public void unknownFieldsUnrecognized() throws Exception {
+ Proto2Message expectedMessage = messageFactory().newMessage();
+ byte[] serializedBytes = expectedMessage.toByteArray();
+ Proto2Empty empty =
+ ExperimentalSerializationUtil.fromByteArray(serializedBytes, Proto2Empty.class);
+
+ // Merge serialized bytes into an empty message, then reserialize and merge it to a new
+ // Proto2Message. Make sure the two messages equal.
+ byte[] roundtripBytes = ExperimentalSerializationUtil.toByteArray(empty);
+ assertEquals(serializedBytes.length, roundtripBytes.length);
+ Proto2Message roundtripMessage =
+ ExperimentalSerializationUtil.fromByteArray(roundtripBytes, Proto2Message.class);
+ assertEquals(expectedMessage, roundtripMessage);
+ }
+
+ @Test
+ public void unknownEnum() throws IOException {
+ // Use unknown fields to hold invalid enum values.
+ UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance();
+ final int outOfRange = 1000;
+ assertNull(TestEnum.forNumber(outOfRange));
+ unknowns.storeField(
+ WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.ONE_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.TWO_VALUE);
+
+ {
+ // Construct a packed enum list.
+ int packedSize =
+ CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE)
+ + CodedOutputStream.computeUInt32SizeNoTag(outOfRange)
+ + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE);
+ ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize);
+ CodedOutputStream packedOut = packedBuilder.getCodedOutput();
+ packedOut.writeEnumNoTag(TestEnum.ONE_VALUE);
+ packedOut.writeEnumNoTag(outOfRange);
+ packedOut.writeEnumNoTag(TestEnum.TWO_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER,
+ WireFormat.WIRETYPE_LENGTH_DELIMITED),
+ packedBuilder.build());
+ }
+ int size = unknowns.getSerializedSize();
+ byte[] output = new byte[size];
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ unknowns.writeTo(codedOutput);
+ codedOutput.flush();
+
+ Proto2Message parsed = ExperimentalSerializationUtil.fromByteArray(output, Proto2Message.class);
+ assertFalse("out-of-range singular enum should not be in message", parsed.hasFieldEnum13());
+ {
+ List<Long> singularEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, singularEnum.size());
+ assertEquals((Long) (long) outOfRange, singularEnum.get(0));
+ }
+ {
+ List<Long> repeatedEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, repeatedEnum.size());
+ assertEquals((Long) (long) outOfRange, repeatedEnum.get(0));
+ }
+ {
+ List<Long> packedRepeatedEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, packedRepeatedEnum.size());
+ assertEquals((Long) (long) outOfRange, packedRepeatedEnum.get(0));
+ }
+ assertEquals(
+ "out-of-range repeated enum should not be in message", 2, parsed.getFieldEnumList30Count());
+ assertEquals(TestEnum.ONE, parsed.getFieldEnumList30(0));
+ assertEquals(TestEnum.TWO, parsed.getFieldEnumList30(1));
+ assertEquals(
+ "out-of-range packed repeated enum should not be in message",
+ 2,
+ parsed.getFieldEnumListPacked44Count());
+ assertEquals(TestEnum.ONE, parsed.getFieldEnumListPacked44(0));
+ assertEquals(TestEnum.TWO, parsed.getFieldEnumListPacked44(1));
+ }
+
+ @Override
+ protected List<Proto2Message> newMessagesMissingRequiredFields() {
+ return messageFactory().newMessagesMissingRequiredFields();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java
new file mode 100755
index 000000000..9cc04ec7c
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.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 static org.junit.Assert.assertEquals;
+
+import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+
+/** Base class for tests using {@link Proto3MessageLite}. */
+public abstract class AbstractProto3LiteSchemaTest extends AbstractSchemaTest<Proto3MessageLite> {
+ @Override
+ protected Proto3MessageLiteFactory messageFactory() {
+ return new Proto3MessageLiteFactory(10, 20, 2, 2);
+ }
+
+ @Override
+ protected List<ByteBuffer> serializedBytesWithInvalidUtf8() throws IOException {
+ List<ByteBuffer> invalidBytes = new ArrayList<>();
+ byte[] invalid = new byte[] {(byte) 0x80};
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(100);
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer);
+ codedOutput.writeByteArray(Proto3MessageLite.FIELD_STRING_9_FIELD_NUMBER, invalid);
+ codedOutput.flush();
+ buffer.flip();
+ invalidBytes.add(buffer);
+ }
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(100);
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer);
+ codedOutput.writeByteArray(Proto3MessageLite.FIELD_STRING_LIST_26_FIELD_NUMBER, invalid);
+ codedOutput.flush();
+ buffer.flip();
+ invalidBytes.add(buffer);
+ }
+ return invalidBytes;
+ }
+
+ @Test
+ public void mergeOptionalMessageFields() throws Exception {
+ Proto3MessageLite message1 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build())
+ .build();
+ Proto3MessageLite message2 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build())
+ .build();
+ Proto3MessageLite message3 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build())
+ .build();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ message1.writeTo(output);
+ message2.writeTo(output);
+ message3.writeTo(output);
+ byte[] data = output.toByteArray();
+
+ Proto3MessageLite merged =
+ ExperimentalSerializationUtil.fromByteArray(data, Proto3MessageLite.class);
+ assertEquals(789, merged.getFieldMessage10().getFieldInt643());
+ assertEquals(456, merged.getFieldMessage10().getFieldInt325());
+ }
+
+ @Test
+ public void oneofFieldsShouldRoundtrip() throws IOException {
+ roundtrip("Field 53", newBuilder().setFieldDouble53(100).build());
+ roundtrip("Field 54", newBuilder().setFieldFloat54(100).build());
+ roundtrip("Field 55", newBuilder().setFieldInt6455(100).build());
+ roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build());
+ roundtrip("Field 57", newBuilder().setFieldInt3257(100).build());
+ roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build());
+ roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build());
+ roundtrip("Field 60", newBuilder().setFieldBool60(true).build());
+ roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build());
+ roundtrip(
+ "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build());
+ roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build());
+ roundtrip("Field 64", newBuilder().setFieldUint3264(100).build());
+ roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build());
+ roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build());
+ roundtrip("Field 67", newBuilder().setFieldSint3267(100).build());
+ roundtrip("Field 68", newBuilder().setFieldSint6468(100).build());
+ }
+
+ @Test
+ public void retainUnknownFields() {
+ // Unknown fields are retained in lite runtime.
+ Proto3MessageLite expectedMessage = messageFactory().newMessage();
+ Proto3EmptyLite empty =
+ ExperimentalSerializationUtil.fromByteArray(
+ expectedMessage.toByteArray(), Proto3EmptyLite.class);
+ assertEquals(expectedMessage.getSerializedSize(), empty.getSerializedSize());
+ }
+
+ @Test
+ public void mapsShouldRoundtrip() throws IOException {
+ roundtrip(
+ "Proto3MessageLiteWithMaps",
+ new Proto3MessageLiteFactory(2, 10, 2, 2).newMessageWithMaps(),
+ Protobuf.getInstance().schemaFor(Proto3MessageLiteWithMaps.class));
+ }
+
+ private static Proto3MessageLite.Builder newBuilder() {
+ return Proto3MessageLite.newBuilder();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java
new file mode 100755
index 000000000..358f1e3b1
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java
@@ -0,0 +1,151 @@
+// 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 com.google.protobuf.testing.Proto3Testing.Proto3Empty;
+import com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+
+/** Base class for tests using {@link Proto3Message}. */
+public abstract class AbstractProto3SchemaTest extends AbstractSchemaTest<Proto3Message> {
+ @Override
+ protected Proto3MessageFactory messageFactory() {
+ return new Proto3MessageFactory(10, 20, 2, 2);
+ }
+
+ @Override
+ protected List<ByteBuffer> serializedBytesWithInvalidUtf8() throws IOException {
+ List<ByteBuffer> invalidBytes = new ArrayList<>();
+ byte[] invalid = new byte[] {(byte) 0x80};
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(100);
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer);
+ codedOutput.writeByteArray(Proto3Message.FIELD_STRING_9_FIELD_NUMBER, invalid);
+ codedOutput.flush();
+ buffer.flip();
+ invalidBytes.add(buffer);
+ }
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(100);
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(buffer);
+ codedOutput.writeByteArray(Proto3Message.FIELD_STRING_LIST_26_FIELD_NUMBER, invalid);
+ codedOutput.flush();
+ buffer.flip();
+ invalidBytes.add(buffer);
+ }
+ return invalidBytes;
+ }
+
+ @Test
+ public void mergeOptionalMessageFields() throws Exception {
+ Proto3Message message1 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(123).clearFieldInt325().build())
+ .build();
+ Proto3Message message2 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().clearFieldInt643().setFieldInt325(456).build())
+ .build();
+ Proto3Message message3 =
+ newBuilder()
+ .setFieldMessage10(newBuilder().setFieldInt643(789).clearFieldInt325().build())
+ .build();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ message1.writeTo(output);
+ message2.writeTo(output);
+ message3.writeTo(output);
+ byte[] data = output.toByteArray();
+
+ Proto3Message merged = ExperimentalSerializationUtil.fromByteArray(data, Proto3Message.class);
+ assertEquals(789, merged.getFieldMessage10().getFieldInt643());
+ assertEquals(456, merged.getFieldMessage10().getFieldInt325());
+ }
+
+ @Test
+ public void oneofFieldsShouldRoundtrip() throws IOException {
+ roundtrip("Field 53", newBuilder().setFieldDouble53(100).build());
+ roundtrip("Field 54", newBuilder().setFieldFloat54(100).build());
+ roundtrip("Field 55", newBuilder().setFieldInt6455(100).build());
+ roundtrip("Field 56", newBuilder().setFieldUint6456(100L).build());
+ roundtrip("Field 57", newBuilder().setFieldInt3257(100).build());
+ roundtrip("Field 58", newBuilder().setFieldFixed6458(100).build());
+ roundtrip("Field 59", newBuilder().setFieldFixed3259(100).build());
+ roundtrip("Field 60", newBuilder().setFieldBool60(true).build());
+ roundtrip("Field 61", newBuilder().setFieldString61(data().getString()).build());
+ roundtrip(
+ "Field 62", newBuilder().setFieldMessage62(newBuilder().setFieldDouble1(100)).build());
+ roundtrip("Field 63", newBuilder().setFieldBytes63(data().getBytes()).build());
+ roundtrip("Field 64", newBuilder().setFieldUint3264(100).build());
+ roundtrip("Field 65", newBuilder().setFieldSfixed3265(100).build());
+ roundtrip("Field 66", newBuilder().setFieldSfixed6466(100).build());
+ roundtrip("Field 67", newBuilder().setFieldSint3267(100).build());
+ roundtrip("Field 68", newBuilder().setFieldSint6468(100).build());
+ }
+
+ @Test
+ public void preserveUnknownFields() {
+ Proto3Message expectedMessage = messageFactory().newMessage();
+ Proto3Empty empty =
+ ExperimentalSerializationUtil.fromByteArray(
+ expectedMessage.toByteArray(), Proto3Empty.class);
+ assertEquals(expectedMessage.getSerializedSize(), empty.getSerializedSize());
+ assertEquals(expectedMessage.toByteString(), empty.toByteString());
+ }
+
+ @Test
+ public void preserveUnknownFieldsProto2() {
+ // Make sure we will be able to preserve valid proto2 wireformat, including those that are not
+ // supported in proto3, e.g. groups.
+ byte[] payload = new Proto2MessageFactory(10, 20, 2, 2).newMessage().toByteArray();
+ Proto3Empty empty = ExperimentalSerializationUtil.fromByteArray(payload, Proto3Empty.class);
+ assertEquals(payload.length, empty.getSerializedSize());
+ }
+
+ @Test
+ public void mapsShouldRoundtrip() throws IOException {
+ roundtrip(
+ "Proto3MessageWithMaps",
+ new Proto3MessageFactory(2, 10, 2, 2).newMessageWithMaps(),
+ Protobuf.getInstance().schemaFor(Proto3MessageWithMaps.class));
+ }
+
+ private static Proto3Message.Builder newBuilder() {
+ return Proto3Message.newBuilder();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java
new file mode 100755
index 000000000..c69a4fd25
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java
@@ -0,0 +1,157 @@
+// 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.assertNotEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+
+public abstract class AbstractSchemaTest<T extends MessageLite> {
+ private Schema<T> schema;
+
+ @Before
+ public void setup() {
+ schema = schema();
+ registerSchemas();
+ }
+
+ // Subclass should override this method if it needs to register more than one schemas.
+ protected void registerSchemas() {
+ // Register this schema with the runtime to support processing of nested messages.
+ Protobuf.getInstance().registerSchemaOverride(schema.newInstance().getClass(), schema);
+ }
+
+ protected abstract Schema<T> schema();
+
+ protected abstract ExperimentalMessageFactory<? extends T> messageFactory();
+
+ @SuppressWarnings("unused")
+ protected List<ByteBuffer> serializedBytesWithInvalidUtf8() throws IOException {
+ return Collections.emptyList();
+ }
+
+ @Test
+ public void randomMessageShouldRoundtrip() throws IOException {
+ roundtrip("", messageFactory().newMessage());
+ }
+
+ @Test
+ public void invalidUtf8StringParsing() throws IOException {
+ for (ByteBuffer invalidUtf8Bytes : serializedBytesWithInvalidUtf8()) {
+ Reader reader = BinaryReader.newInstance(invalidUtf8Bytes, /* bufferIsImmutable= */ true);
+
+ T newMsg = schema.newInstance();
+ try {
+ schema.mergeFrom(newMsg, reader, ExtensionRegistryLite.getEmptyRegistry());
+ fail("should throw invalid ");
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+ }
+
+ @Test
+ public void mergeFromByteArrayFastPathMayThrowIndexOutOfBoundsException() throws IOException {
+ if (!Android.isOnAndroidDevice()) {
+ // Skip this test if not on Android.
+ return;
+ }
+ byte[] data = messageFactory().newMessage().toByteArray();
+ int exceptionCount = 0;
+ for (int i = 0; i <= data.length; i++) {
+ byte[] truncatedData = Arrays.copyOf(data, i);
+ try {
+ T message = schema.newInstance();
+ // Test that this method throws the expected exceptions.
+ schema.mergeFrom(message, truncatedData, 0, i, new ArrayDecoders.Registers());
+ } catch (InvalidProtocolBufferException e) {
+ // Ignore expected exceptions.
+ } catch (IndexOutOfBoundsException e) {
+ exceptionCount += 1;
+ }
+ }
+ assertNotEquals(0, exceptionCount);
+ }
+
+ protected static final <M extends MessageLite> void roundtrip(
+ String failureMessage, M msg, Schema<M> schema) throws IOException {
+ byte[] serializedBytes = ExperimentalSerializationUtil.toByteArray(msg, schema);
+ assertEquals(failureMessage, msg.getSerializedSize(), serializedBytes.length);
+
+ // Now read it back in and verify it matches the original.
+ if (Android.isOnAndroidDevice()) {
+ // Test the fast path on Android.
+ M newMsg = schema.newInstance();
+ schema.mergeFrom(
+ newMsg, serializedBytes, 0, serializedBytes.length, new ArrayDecoders.Registers());
+ schema.makeImmutable(newMsg);
+ assertEquals(failureMessage, msg, newMsg);
+ }
+ M newMsg = schema.newInstance();
+ Reader reader = BinaryReader.newInstance(ByteBuffer.wrap(serializedBytes), true);
+ schema.mergeFrom(newMsg, reader, ExtensionRegistryLite.getEmptyRegistry());
+ schema.makeImmutable(newMsg);
+
+ assertEquals(failureMessage, msg, newMsg);
+ }
+
+ protected final void roundtrip(String failureMessage, T msg) throws IOException {
+ roundtrip(failureMessage, msg, schema);
+ }
+
+ protected final ExperimentalTestDataProvider data() {
+ return messageFactory().dataProvider();
+ }
+
+ protected List<T> newMessagesMissingRequiredFields() {
+ return Collections.emptyList();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRequiredFields() throws Exception {
+ for (T msg : newMessagesMissingRequiredFields()) {
+ if (schema.isInitialized(msg)) {
+ assertEquals("", msg.toString());
+ msg = (T) msg.toBuilder().build();
+ }
+ assertFalse(schema.isInitialized(msg));
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java
new file mode 100755
index 000000000..037173b66
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java
@@ -0,0 +1,236 @@
+// 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.ArrayDecoders.Registers;
+import java.io.IOException;
+import junit.framework.TestCase;
+
+public class ArrayDecodersTest extends TestCase {
+
+ private static final int TAG = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ private static final ByteString NEGATIVE_SIZE_0 = generateNegativeLength(0);
+ private static final ByteString NEGATIVE_SIZE_1 = generateNegativeLength(1);
+
+ private Registers registers;
+
+ @Override
+ public void setUp() {
+ registers = new Registers();
+ registers.int1 = TAG;
+ }
+
+ public void testException_decodeString() {
+ try {
+ ArrayDecoders.decodeString(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeStringRequireUtf8() {
+ try {
+ ArrayDecoders.decodeStringRequireUtf8(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeBytes() {
+ try {
+ ArrayDecoders.decodeBytes(NEGATIVE_SIZE_0.toByteArray(), 0, registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeStringList_first() {
+ try {
+ ArrayDecoders.decodeStringList(
+ TAG,
+ NEGATIVE_SIZE_0.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_0.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeStringList_second() {
+ try {
+ ArrayDecoders.decodeStringList(
+ TAG,
+ NEGATIVE_SIZE_1.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_1.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeStringListRequireUtf8_first() {
+ try {
+ ArrayDecoders.decodeStringListRequireUtf8(
+ TAG,
+ NEGATIVE_SIZE_0.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_0.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeStringListRequireUtf8_second() {
+ try {
+ ArrayDecoders.decodeStringListRequireUtf8(
+ TAG,
+ NEGATIVE_SIZE_1.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_1.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeBytesList_first() {
+ try {
+ ArrayDecoders.decodeBytesList(
+ TAG,
+ NEGATIVE_SIZE_0.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_0.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeBytesList_second() {
+ try {
+ ArrayDecoders.decodeBytesList(
+ TAG,
+ NEGATIVE_SIZE_1.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_1.size(),
+ new ProtobufArrayList<Object>(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeUnknownField() {
+ try {
+ ArrayDecoders.decodeUnknownField(
+ TAG,
+ NEGATIVE_SIZE_0.toByteArray(),
+ 0,
+ NEGATIVE_SIZE_0.size(),
+ UnknownFieldSetLite.newInstance(),
+ registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ public void testException_decodeHugeField() {
+ byte[] badBytes =
+ new byte[] {
+ (byte) 0x80, (byte) 0xFF, (byte) 0xFF, (byte) 0xEF, 0x73, 0x74, 0x69, 0x6E, 0x67
+ };
+ try {
+ ArrayDecoders.decodeUnknownField(
+ TAG, badBytes, 0, badBytes.length, UnknownFieldSetLite.newInstance(), registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+
+ try {
+ ArrayDecoders.decodeBytes(badBytes, 0, registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+
+ byte[] badBytesList =
+ new byte[] {
+ 0x01,
+ 0x77,
+ 0x0A,
+ (byte) 0x80,
+ (byte) 0xFF,
+ (byte) 0xFF,
+ (byte) 0xEF,
+ 0x73,
+ 0x74,
+ 0x69,
+ 0x6E,
+ 0x67
+ };
+ try {
+ ArrayDecoders.decodeBytesList(
+ TAG, badBytesList, 0, badBytes.length, new ProtobufArrayList<>(), registers);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
+ private static ByteString generateNegativeLength(int count) {
+ try {
+ ByteString.Output byteStringOutput = ByteString.newOutput();
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(byteStringOutput);
+
+ // Write out count - 1 valid 0 length fields; we only write out tags after the field since
+ // ArrayDecoders expects the first tag to already have been parsed.
+ for (int i = 0; i < count; i++) {
+ codedOutput.writeInt32NoTag(0);
+ codedOutput.writeInt32NoTag(TAG);
+ }
+
+ // Write out a negative length
+ codedOutput.writeInt32NoTag(-1);
+
+ codedOutput.flush();
+
+ return byteStringOutput.toByteString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java b/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java
new file mode 100755
index 000000000..cda2998f5
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java
@@ -0,0 +1,90 @@
+// 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 com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class BinaryProtocolTest {
+ @Before
+ public void setup() {
+ TestSchemas.registerGenericProto2Schemas();
+
+ Protobuf.getInstance()
+ .registerSchemaOverride(Proto3Message.class, TestSchemas.genericProto3Schema);
+ }
+
+ @Test
+ public void proto3Roundtrip() throws Exception {
+ Proto3Message expected = new Proto3MessageFactory(5, 10, 2, 2).newMessage();
+ byte[] expectedBytes = expected.toByteArray();
+
+ // Deserialize with BinaryReader and verify that the message matches the original.
+ Proto3Message result =
+ ExperimentalSerializationUtil.fromByteArray(expectedBytes, Proto3Message.class);
+ assertEquals(expected, result);
+
+ // Now write it back out using BinaryWriter and verify the output length.
+ byte[] actualBytes = ExperimentalSerializationUtil.toByteArray(result);
+ Assert.assertEquals(expectedBytes.length, actualBytes.length);
+
+ // Read back in the bytes and verify that it matches the original message.
+ Proto3Message actual = Proto3Message.parseFrom(actualBytes);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void proto2Roundtrip() throws Exception {
+ Proto2Message expected = new Proto2MessageFactory(5, 10, 2, 2).newMessage();
+ byte[] expectedBytes = expected.toByteArray();
+
+ // Deserialize with BinaryReader and verify that the message matches the original.
+ Proto2Message result =
+ ExperimentalSerializationUtil.fromByteArray(expectedBytes, Proto2Message.class);
+ assertEquals(expected, result);
+
+ // Now write it back out using BinaryWriter and verify the output length.
+ byte[] actualBytes = ExperimentalSerializationUtil.toByteArray(result);
+ Assert.assertEquals(expectedBytes.length, actualBytes.length);
+
+ // Read back in the bytes and verify that it matches the original message.
+ Proto2Message actual = Proto2Message.parseFrom(actualBytes);
+ assertEquals(expected, actual);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java b/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java
new file mode 100755
index 000000000..96319d93c
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.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 static org.junit.Assert.assertEquals;
+
+import protobuf_unittest.UnittestProto.TestPackedTypes;
+import proto3_unittest.UnittestProto3;
+import protobuf_unittest.TestCachedFieldSizeMessage;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class CachedFieldSizeTest {
+ // Regression test for b/74087933
+ @Test
+ public void testCachedFieldSize() throws Exception {
+ TestCachedFieldSizeMessage.Builder builder = TestCachedFieldSizeMessage.newBuilder();
+ builder.setProto2Child(TestUtil.getPackedSet());
+ builder.setProto3Child(
+ UnittestProto3.TestPackedTypes.parseFrom(TestUtil.getPackedSet().toByteArray()));
+ TestCachedFieldSizeMessage message = builder.build();
+
+ // Serialize once to cache all field sizes. This will use the experimental runtime because
+ // the proto has optimize_for = CODE_SIZE.
+ message.toByteArray();
+ // Serialize individual submessages. This will use the generated implementation. If the
+ // experimental runtime hasn't set the correct cached size, this will throw an exception.
+ byte[] data2 = message.getProto2Child().toByteArray();
+ byte[] data3 = message.getProto3Child().toByteArray();
+
+ // Make sure the serialized data is correct.
+ assertEquals(message.getProto2Child(), TestPackedTypes.parseFrom(data2));
+ assertEquals(message.getProto3Child(), UnittestProto3.TestPackedTypes.parseFrom(data3));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java b/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java
new file mode 100755
index 000000000..a24b48b51
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import java.io.IOException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class CodedAdapterTest {
+ @Before
+ public void setup() {
+ TestSchemas.registerGenericProto2Schemas();
+
+ Protobuf.getInstance()
+ .registerSchemaOverride(Proto3Message.class, TestSchemas.genericProto3Schema);
+ }
+
+ @Test
+ public void proto3Roundtrip() throws Exception {
+ Proto3Message expected = new Proto3MessageFactory(5, 10, 2, 2).newMessage();
+ byte[] expectedBytes = expected.toByteArray();
+
+ // Deserialize with BinaryReader and verify that the message matches the original.
+ Proto3Message result = fromByteArray(expectedBytes, Proto3Message.class);
+ assertEquals(expected, result);
+
+ // Now write it back out using BinaryWriter and verify the output length.
+ byte[] actualBytes = toByteArray(result, expectedBytes.length);
+
+ // Read back in the bytes and verify that it matches the original message.
+ Proto3Message actual = Proto3Message.parseFrom(actualBytes);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void proto2Roundtrip() throws Exception {
+ Proto2Message expected = new Proto2MessageFactory(5, 10, 2, 2).newMessage();
+ byte[] expectedBytes = expected.toByteArray();
+
+ // Deserialize with BinaryReader and verify that the message matches the original.
+ Proto2Message result = fromByteArray(expectedBytes, Proto2Message.class);
+ assertEquals(expected, result);
+
+ // Now write it back out using BinaryWriter and verify the output length.
+ byte[] actualBytes = toByteArray(result, expectedBytes.length);
+
+ // Read back in the bytes and verify that it matches the original message.
+ Proto2Message actual = Proto2Message.parseFrom(actualBytes);
+ assertEquals(expected, actual);
+ }
+
+ public static <T> byte[] toByteArray(T msg, int size) throws Exception {
+ Schema<T> schema = Protobuf.getInstance().schemaFor(msg);
+ byte[] out = new byte[size];
+ CodedOutputStreamWriter writer =
+ CodedOutputStreamWriter.forCodedOutput(CodedOutputStream.newInstance(out));
+ schema.writeTo(msg, writer);
+ assertEquals(out.length, writer.getTotalBytesWritten());
+ return out;
+ }
+
+ public static <T> T fromByteArray(byte[] data, Class<T> messageType) {
+ Schema<T> schema = Protobuf.getInstance().schemaFor(messageType);
+ try {
+ T msg = schema.newInstance();
+ schema.mergeFrom(
+ msg,
+ CodedInputStreamReader.forCodedInput(CodedInputStream.newInstance(data)),
+ ExtensionRegistryLite.EMPTY_REGISTRY_LITE);
+ return msg;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 9c5d6dafb..532052cdb 100644
--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -44,6 +44,7 @@ import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import junit.framework.TestCase;
/**
@@ -1195,4 +1196,59 @@ public class CodedInputStreamTest extends TestCase {
// Expected
}
}
+
+ public void testMaliciousInputStream() throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream);
+ codedOutputStream.writeByteArrayNoTag(new byte[] { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5 });
+ codedOutputStream.flush();
+ final List<byte[]> maliciousCapture = new ArrayList<>();
+ InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()) {
+ @Override
+ public synchronized int read(byte[] b, int off, int len) {
+ maliciousCapture.add(b);
+ return super.read(b, off, len);
+ }
+ };
+
+ // test ByteString
+
+ CodedInputStream codedInputStream = CodedInputStream.newInstance(inputStream, 1);
+ ByteString byteString = codedInputStream.readBytes();
+ assertEquals(0x0, byteString.byteAt(0));
+ maliciousCapture.get(1)[0] = 0x9;
+ assertEquals(0x0, byteString.byteAt(0));
+
+ // test ByteBuffer
+
+ inputStream.reset();
+ maliciousCapture.clear();
+ codedInputStream = CodedInputStream.newInstance(inputStream, 1);
+ ByteBuffer byteBuffer = codedInputStream.readByteBuffer();
+ assertEquals(0x0, byteBuffer.get(0));
+ maliciousCapture.get(1)[0] = 0x9;
+ assertEquals(0x0, byteBuffer.get(0));
+
+
+ // test byte[]
+
+ inputStream.reset();
+ maliciousCapture.clear();
+ codedInputStream = CodedInputStream.newInstance(inputStream, 1);
+ byte[] byteArray = codedInputStream.readByteArray();
+ assertEquals(0x0, byteArray[0]);
+ maliciousCapture.get(1)[0] = 0x9;
+ assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
+
+ // test rawBytes
+
+ inputStream.reset();
+ maliciousCapture.clear();
+ codedInputStream = CodedInputStream.newInstance(inputStream, 1);
+ int length = codedInputStream.readRawVarint32();
+ byteArray = codedInputStream.readRawBytes(length);
+ assertEquals(0x0, byteArray[0]);
+ maliciousCapture.get(1)[0] = 0x9;
+ assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
+ }
}
diff --git a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
index 5f9132401..c222ff377 100644
--- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -30,6 +30,8 @@
package com.google.protobuf;
+import protobuf_unittest.NestedExtension;
+import protobuf_unittest.NonNestedExtension;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
import com.google.protobuf.DescriptorProtos.EnumDescriptorProto;
import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;
@@ -779,4 +781,23 @@ public class DescriptorsTest extends TestCase {
assertEquals("FIELDNAME5", d.getFields().get(4).getJsonName());
assertEquals("@type", d.getFields().get(5).getJsonName());
}
+
+ public void testExtensionRenamesKeywords() {
+ assertTrue(NonNestedExtension.if_ instanceof GeneratedMessage.GeneratedExtension);
+ assertTrue(
+ NestedExtension.MyNestedExtension.default_
+ instanceof GeneratedMessage.GeneratedExtension);
+
+ NonNestedExtension.MessageToBeExtended msg =
+ NonNestedExtension.MessageToBeExtended.newBuilder()
+ .setExtension(NonNestedExtension.if_, "!fi")
+ .build();
+ assertEquals("!fi", msg.getExtension(NonNestedExtension.if_));
+
+ msg =
+ NonNestedExtension.MessageToBeExtended.newBuilder()
+ .setExtension(NestedExtension.MyNestedExtension.default_, 8)
+ .build();
+ assertEquals(8, msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue());
+ }
}
diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java b/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java
new file mode 100755
index 000000000..60c8609cf
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java
@@ -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.
+
+package com.google.protobuf;
+
+/** Interface for a test factory for messages. */
+public interface ExperimentalMessageFactory<T extends MessageLite> {
+ /** Creates a new random message instance. */
+ T newMessage();
+
+ /** Gets the underlying data provider. */
+ ExperimentalTestDataProvider dataProvider();
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java b/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java
new file mode 100755
index 000000000..05aaa6752
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java
@@ -0,0 +1,113 @@
+// 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;
+import java.util.Queue;
+
+/** Utilities for serialization. */
+public class ExperimentalSerializationUtil {
+
+ /**
+ * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter}.
+ */
+ public static <T> byte[] toByteArray(T msg) throws IOException {
+ return toByteArray(msg, Protobuf.getInstance().schemaFor(msg));
+ }
+
+ /**
+ * Serializes the given message to a byte array using {@link com.google.protobuf.BinaryWriter}
+ * with a customized Schema.
+ */
+ public static <T> byte[] toByteArray(T msg, Schema<T> schema) throws IOException {
+ BinaryWriter writer = BinaryWriter.newHeapInstance(BufferAllocator.unpooled());
+ schema.writeTo(msg, writer);
+
+ byte[] out = new byte[writer.getTotalBytesWritten()];
+ int outPos = 0;
+ Queue<AllocatedBuffer> buffers = writer.complete();
+ while (true) {
+ AllocatedBuffer buffer = buffers.poll();
+ if (buffer == null) {
+ break;
+ }
+ int length = buffer.limit() - buffer.position();
+ System.arraycopy(
+ buffer.array(), buffer.arrayOffset() + buffer.position(), out, outPos, length);
+ outPos += length;
+ }
+ if (out.length != outPos) {
+ throw new IllegalArgumentException("Failed to serialize test message");
+ }
+ return out;
+ }
+
+ /** Deserializes a message from the given byte array. */
+ public static <T> T fromByteArray(byte[] data, Class<T> messageType) {
+ if (Android.isOnAndroidDevice()) {
+ return fromByteArrayFastPath(data, messageType);
+ } else {
+ return fromByteArray(data, messageType, ExtensionRegistryLite.getEmptyRegistry());
+ }
+ }
+
+ /**
+ * Deserializes a message from the given byte array using {@link com.google.protobuf.BinaryReader}
+ * with an extension registry and a customized Schema.
+ */
+ public static <T> T fromByteArray(
+ byte[] data, Class<T> messageType, ExtensionRegistryLite extensionRegistry) {
+ try {
+ Schema<T> schema = Protobuf.getInstance().schemaFor(messageType);
+ T msg = schema.newInstance();
+ schema.mergeFrom(
+ msg, BinaryReader.newInstance(ByteBuffer.wrap(data), true), extensionRegistry);
+ schema.makeImmutable(msg);
+ return msg;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Deserializes a lite message from the given byte array using fast path. */
+ private static <T> T fromByteArrayFastPath(byte[] data, Class<T> messageType) {
+ try {
+ Schema<T> schema = Protobuf.getInstance().schemaFor(messageType);
+ T msg = schema.newInstance();
+ schema.mergeFrom(msg, data, 0, data.length, new ArrayDecoders.Registers());
+ schema.makeImmutable(msg);
+ return msg;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java b/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java
new file mode 100755
index 000000000..3ef93ac9f
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.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.util.Random;
+
+/** Utility class that provides data primitives for filling out protobuf messages. */
+public final class ExperimentalTestDataProvider {
+ private static final Random RANDOM = new Random(100);
+
+ private final Varint32Provider varint32s = new Varint32Provider();
+ private final Varint64Provider varint64s = new Varint64Provider();
+ private final int stringLength;
+
+ public ExperimentalTestDataProvider(int stringLength) {
+ this.stringLength = stringLength;
+ }
+
+ public double getDouble() {
+ double value = 0.0;
+ while (Double.compare(0.0, value) == 0) {
+ value = RANDOM.nextDouble();
+ }
+ return value;
+ }
+
+ public float getFloat() {
+ float value = 0.0f;
+ while (Float.compare(0.0f, value) == 0) {
+ value = RANDOM.nextFloat();
+ }
+ return value;
+ }
+
+ public long getLong() {
+ return varint64s.getLong();
+ }
+
+ public int getInt() {
+ return varint32s.getInt();
+ }
+
+ public boolean getBool() {
+ return true;
+ }
+
+ public int getEnum() {
+ return Math.abs(getInt()) % 3;
+ }
+
+ public String getString() {
+ StringBuilder builder = new StringBuilder(stringLength);
+ for (int i = 0; i < stringLength; ++i) {
+ builder.append((char) (RANDOM.nextInt('z' - 'a') + 'a'));
+ }
+ return builder.toString();
+ }
+
+ public ByteString getBytes() {
+ return ByteString.copyFromUtf8(getString());
+ }
+
+ /**
+ * Iterator over integer values. Uses a simple distribution over 32-bit varints (generally
+ * favoring smaller values).
+ */
+ private static final class Varint32Provider {
+ private static final int[][] VALUES = {
+ new int[] {1, 50, 100, 127}, // 1 byte values
+ new int[] {128, 500, 10000, 16383}, // 2 bytes values
+ new int[] {16384, 50000, 1000000, 2097151}, // 3 bytes values
+ new int[] {2097152, 10000000, 200000000, 268435455}, // 4 bytes values
+ new int[] {268435456, 0x30000000, 0x7FFFFFFF, 0xFFFFFFFF} // 5 bytes values
+ };
+
+ /** Number of samples that should be taken from each value array. */
+ private static final int[] NUM_SAMPLES = {3, 2, 1, 1, 2};
+
+ /**
+ * The index into the {@link #VALUES} array that identifies the list of samples currently being
+ * iterated over.
+ */
+ private int listIndex;
+
+ /** The index of the next sample within a list. */
+ private int sampleIndex;
+
+ /** The number of successive samples that have been taken from the current list. */
+ private int samplesTaken;
+
+ public int getInt() {
+ if (samplesTaken++ > NUM_SAMPLES[listIndex]) {
+ // Done taking samples from this list. Go to the next one.
+ listIndex = (listIndex + 1) % VALUES.length;
+ sampleIndex = 0;
+ samplesTaken = 0;
+ }
+
+ int value = VALUES[listIndex][sampleIndex];
+
+ // All lists are exactly 4 long (i.e. power of 2), so we can optimize the mod operation
+ // with masking.
+ sampleIndex = (sampleIndex + 1) & 3;
+
+ return value;
+ }
+ }
+
+ /**
+ * Iterator over integer values. Uses a simple distribution over 64-bit varints (generally
+ * favoring smaller values).
+ */
+ private static final class Varint64Provider {
+ private static final long[][] VALUES = {
+ new long[] {1, 50, 100, 127},
+ new long[] {128, 500, 10000, 16383},
+ new long[] {16384, 50000, 1000000, 2097151},
+ new long[] {2097152, 10000000, 200000000, 268435455},
+ new long[] {268435456, 0x30000000, 0x7FFFFFFF, 34359738367L},
+ new long[] {34359738368L, 2000000000000L, 4000000000000L, 4398046511103L},
+ new long[] {4398046511104L, 200000000000000L, 500000000000000L, 562949953421311L},
+ new long[] {0x4000000000000L, 0x5000000000000L, 0x6000000000000L, 0x0FFFFFFFFFFFFFFL},
+ new long[] {0x100000000000000L, 0x3FFFFFFFFFFFFFFFL, 0x5FFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL},
+ new long[] {
+ 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL, 0xFFFFFFFFFFFFFFFFL
+ }
+ };
+
+ /** Number of samples that should be taken from each value array. */
+ private static final int[] NUM_SAMPLES = {4, 2, 2, 1, 1, 1, 1, 2, 2, 4};
+
+ /**
+ * The index into the {@link #VALUES} array that identifies the list of samples currently being
+ * iterated over.
+ */
+ private int listIndex;
+
+ /** The index of the next sample within a list. */
+ private int sampleIndex;
+
+ /** The number of successive samples that have been taken from the current list. */
+ private int samplesTaken;
+
+ public long getLong() {
+ if (samplesTaken++ > NUM_SAMPLES[listIndex]) {
+ // Done taking samples from this list. Go to the next one.
+ listIndex = (listIndex + 1) % VALUES.length;
+ sampleIndex = 0;
+ samplesTaken = 0;
+ }
+
+ long value = VALUES[listIndex][sampleIndex];
+
+ // All lists are exactly 4 long (i.e. power of 2), so we can optimize the mod operation
+ // with masking.
+ sampleIndex = (sampleIndex + 1) & 3;
+
+ return value;
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
index 30fd14794..3eb0cedc4 100644
--- a/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java
@@ -30,8 +30,6 @@
package com.google.protobuf;
-import protobuf_unittest.NestedExtension;
-import protobuf_unittest.NestedExtensionLite;
import protobuf_unittest.NonNestedExtension;
import protobuf_unittest.NonNestedExtensionLite;
import java.lang.reflect.Method;
@@ -71,8 +69,6 @@ public class ExtensionRegistryFactoryTest extends TestCase {
void testAdd();
void testAdd_immutable();
-
- void testExtensionRenamesKeywords();
}
/** Test implementations for the non-Lite usage of ExtensionRegistryFactory. */
@@ -160,23 +156,6 @@ public class ExtensionRegistryFactoryTest extends TestCase {
} catch (IllegalArgumentException expected) {
}
}
-
- @Override
- public void testExtensionRenamesKeywords() {
- assertTrue(NonNestedExtension.if_ instanceof GeneratedMessage.GeneratedExtension);
- assertTrue(NestedExtension.MyNestedExtension.default_ instanceof GeneratedMessage.GeneratedExtension);
-
- NonNestedExtension.MessageToBeExtended msg =
- NonNestedExtension.MessageToBeExtended.newBuilder()
- .setExtension(NonNestedExtension.if_, "!fi")
- .build();
- assertEquals("!fi", msg.getExtension(NonNestedExtension.if_));
-
- msg = NonNestedExtension.MessageToBeExtended.newBuilder()
- .setExtension(NestedExtension.MyNestedExtension.default_, 8)
- .build();
- assertEquals(8, msg.getExtension(NestedExtension.MyNestedExtension.default_).intValue());
- }
}
/** Test implementations for the Lite usage of ExtensionRegistryFactory. */
@@ -223,23 +202,6 @@ public class ExtensionRegistryFactoryTest extends TestCase {
} catch (UnsupportedOperationException expected) {
}
}
-
- @Override
- public void testExtensionRenamesKeywords() {
- assertTrue(NonNestedExtensionLite.package_ instanceof GeneratedMessageLite.GeneratedExtension);
- assertTrue(NestedExtensionLite.MyNestedExtensionLite.private_ instanceof GeneratedMessageLite.GeneratedExtension);
-
- NonNestedExtensionLite.MessageLiteToBeExtended msg =
- NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder()
- .setExtension(NonNestedExtensionLite.package_, true)
- .build();
- assertTrue(msg.getExtension(NonNestedExtensionLite.package_));
-
- msg = NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder()
- .setExtension(NestedExtensionLite.MyNestedExtensionLite.private_, 2.4)
- .build();
- assertEquals(2.4, msg.getExtension(NestedExtensionLite.MyNestedExtensionLite.private_), 0.001);
- }
}
/** Defines a suite of tests which the JUnit3 runner retrieves by reflection. */
@@ -311,7 +273,10 @@ public class ExtensionRegistryFactoryTest extends TestCase {
resolveClass(loadedClass);
}
}
- } catch (ClassNotFoundException e) {
+ } catch (ClassNotFoundException | SecurityException e) {
+ // Java 8+ would throw a SecurityException if we attempt to find a loaded class from
+ // java.lang.* package. We don't really care about those anyway, so just delegate to the
+ // parent class loader.
loadedClass = super.loadClass(name, resolve);
}
return loadedClass;
diff --git a/java/core/src/test/java/com/google/protobuf/MapLiteTest.java b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java
new file mode 100755
index 000000000..d18fd13e0
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/MapLiteTest.java
@@ -0,0 +1,894 @@
+// 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.assertArrayEquals;
+
+import map_lite_test.MapTestProto.BizarroTestMap;
+import map_lite_test.MapTestProto.TestMap;
+import map_lite_test.MapTestProto.TestMap.MessageValue;
+import map_lite_test.MapTestProto.TestMapOrBuilder;
+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 MapLiteTest 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 usingMutableMapBuilder = TestMap.newBuilder();
+ setMapValues(usingMutableMapBuilder);
+ TestMap usingMutableMap = usingMutableMapBuilder.build();
+ assertMapValuesSet(usingMutableMap);
+
+ TestMap.Builder usingAccessorsBuilder = TestMap.newBuilder();
+ setMapValues(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 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());
+ assertEquals(newMap(1, 2), builder.getInt32ToInt32Field());
+ message = builder.build();
+ 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 testMapFieldClear() {
+ TestMap.Builder builder = TestMap.newBuilder().putInt32ToInt32Field(1, 2);
+ builder.clearInt32ToInt32Field();
+ assertEquals(0, builder.getInt32ToInt32FieldCount());
+ }
+
+ 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 testPutAllForUnknownEnumValues() throws Exception {
+ TestMap.Builder sourceBuilder =
+ TestMap.newBuilder()
+ .putInt32ToEnumFieldValue(0, 0)
+ .putInt32ToEnumFieldValue(1, 1)
+ .putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value.
+ TestMap source = sourceBuilder.build();
+
+ TestMap.Builder destinationBuilder = TestMap.newBuilder();
+ destinationBuilder.putAllInt32ToEnumFieldValue(source.getInt32ToEnumFieldValue());
+ TestMap destination = destinationBuilder.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)
+ .putInt32ToEnumFieldValue(2, 1000); // unknown value.
+ TestMap message = builder.build();
+
+ assertEquals(0, message.getInt32ToEnumFieldValueOrThrow(0));
+ assertEquals(1, message.getInt32ToEnumFieldValueOrThrow(1));
+ assertEquals(1000, message.getInt32ToEnumFieldValueOrThrow(2));
+ assertEquals(3, 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();
+ 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(0, map.getInt32ToInt32FieldOrDefault(5, -1));
+
+ 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(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
+
+ 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(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
+ }
+
+ 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.
+
+ // 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 testUnknownEnumValues() throws Exception {
+ TestMap.Builder builder =
+ TestMap.newBuilder()
+ .putInt32ToEnumFieldValue(0, 0)
+ .putInt32ToEnumFieldValue(1, 1)
+ .putInt32ToEnumFieldValue(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));
+
+ builder.putAllInt32ToEnumFieldValue(newMap(2, 1000)); // unknown value.
+ message = builder.build();
+ assertEquals(TestMap.EnumValue.UNRECOGNIZED, message.getInt32ToEnumField().get(2));
+
+ // 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.
+ assertEquals(message2.getInt32ToEnumField(), message.getInt32ToEnumField());
+ }
+
+ public void testIterationOrder() throws Exception {
+ TestMap.Builder builder = TestMap.newBuilder();
+ setMapValues(builder);
+ TestMap message = builder.build();
+
+ assertEquals(
+ Arrays.asList("1", "2", "3"), new ArrayList<>(message.getStringToInt32Field().keySet()));
+ }
+
+ 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.getInt32ToEnumFieldValue(), message.getInt32ToEnumFieldValueMap());
+ 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(
+ TestMap.EnumValue.BAR.getNumber(),
+ 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);
+ 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(
+ 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.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
+ }
+ }
+
+ private static <K, V> Map<K, V> newMap(K key1, V value1) {
+ Map<K, V> map = new HashMap<>();
+ 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<>();
+ map.put(key1, value1);
+ map.put(key2, value2);
+ return map;
+ }
+
+ public void testMap_withNulls() {
+ TestMap.Builder builder = TestMap.newBuilder();
+
+ try {
+ builder.putStringToInt32Field(null, 3);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ builder.putAllStringToInt32Field(newMap(null, 3, "hi", 4));
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ builder.putInt32ToMessageField(3, null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ builder.putAllInt32ToMessageField(
+ MapLiteTest.<Integer, MessageValue>newMap(4, null, 5, null));
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ builder.putAllInt32ToMessageField(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ assertArrayEquals(new byte[0], builder.build().toByteArray());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java b/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java
new file mode 100755
index 000000000..2397d2ebc
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/PackedFieldTest.java
@@ -0,0 +1,232 @@
+// 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.PackedFieldTestProto.TestAllTypes;
+import com.google.protobuf.PackedFieldTestProto.TestAllTypes.NestedEnum;
+import com.google.protobuf.PackedFieldTestProto.TestUnpackedTypes;
+import junit.framework.TestCase;
+
+/** Tests primitive repeated fields in proto3 are packed in wire format. */
+public class PackedFieldTest extends TestCase {
+ static final ByteString expectedPackedRawBytes =
+ ByteString.copyFrom(
+ new byte[] {
+ (byte) 0xFA,
+ 0x01,
+ 0x01,
+ 0x01, // repeated int32
+ (byte) 0x82,
+ 0x02,
+ 0x01,
+ 0x01, // repeated int64
+ (byte) 0x8A,
+ 0x02,
+ 0x01,
+ 0x01, // repeated uint32
+ (byte) 0x92,
+ 0x02,
+ 0x01,
+ 0x01, // repeated uint64
+ (byte) 0x9A,
+ 0x02,
+ 0x01,
+ 0x02, // repeated sint32
+ (byte) 0xA2,
+ 0x02,
+ 0x01,
+ 0x02, // repeated sint64
+ (byte) 0xAA,
+ 0x02,
+ 0x04,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated fixed32
+ (byte) 0xB2,
+ 0x02,
+ 0x08,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated fixed64
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ (byte) 0xBA,
+ 0x02,
+ 0x04,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated sfixed32
+ (byte) 0xC2,
+ 0x02,
+ 0x08,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated sfixed64
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ (byte) 0xCA,
+ 0x02,
+ 0x04,
+ 0x00,
+ 0x00,
+ (byte) 0x80,
+ 0x3f, // repeated float
+ (byte) 0xD2,
+ 0x02,
+ 0x08,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00, // repeated double
+ 0x00,
+ 0x00,
+ (byte) 0xf0,
+ 0x3f,
+ (byte) 0xDA,
+ 0x02,
+ 0x01,
+ 0x01, // repeated bool
+ (byte) 0x9A,
+ 0x03,
+ 0x01,
+ 0x01 // repeated nested enum
+ });
+
+ static final ByteString expectedUnpackedRawBytes =
+ ByteString.copyFrom(
+ new byte[] {
+ 0x08,
+ 0x01, // repeated int32
+ 0x10,
+ 0x01, // repeated int64
+ 0x18,
+ 0x01, // repeated uint32
+ 0x20,
+ 0x01, // repeated uint64
+ 0x28,
+ 0x02, // repeated sint32
+ 0x30,
+ 0x02, // repeated sint64
+ 0x3D,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated fixed32
+ 0x41,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated fixed64
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x4D,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated sfixed32
+ 0x51,
+ 0x01,
+ 0x00,
+ 0x00,
+ 0x00, // repeated sfixed64
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x5D,
+ 0x00,
+ 0x00,
+ (byte) 0x80,
+ 0x3f, // repeated float
+ 0x61,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00, // repeated double
+ 0x00,
+ 0x00,
+ (byte) 0xf0,
+ 0x3f,
+ 0x68,
+ 0x01, // repeated bool
+ 0x70,
+ 0x01, // repeated nested enum
+ });
+
+ public void testPackedGeneratedMessage() throws Exception {
+ TestAllTypes message = TestAllTypes.parseFrom(expectedPackedRawBytes);
+ assertEquals(expectedPackedRawBytes, message.toByteString());
+ }
+
+ public void testPackedDynamicMessageSerialize() throws Exception {
+ DynamicMessage message =
+ DynamicMessage.parseFrom(TestAllTypes.getDescriptor(), expectedPackedRawBytes);
+ assertEquals(expectedPackedRawBytes, message.toByteString());
+ }
+
+ public void testUnpackedGeneratedMessage() throws Exception {
+ TestUnpackedTypes message = TestUnpackedTypes.parseFrom(expectedUnpackedRawBytes);
+ assertEquals(expectedUnpackedRawBytes, message.toByteString());
+ }
+
+ public void testUnPackedDynamicMessageSerialize() throws Exception {
+ DynamicMessage message =
+ DynamicMessage.parseFrom(TestUnpackedTypes.getDescriptor(), expectedUnpackedRawBytes);
+ assertEquals(expectedUnpackedRawBytes, message.toByteString());
+ }
+
+ // Make sure we haven't screwed up the code generation for packing fields by default.
+ public void testPackedSerialization() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .addRepeatedInt32(1234)
+ .addRepeatedNestedEnum(NestedEnum.BAR)
+ .build();
+
+ CodedInputStream in = CodedInputStream.newInstance(message.toByteArray());
+
+ while (!in.isAtEnd()) {
+ int tag = in.readTag();
+ assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag));
+ in.skipField(tag);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java
new file mode 100755
index 000000000..eb2dc3dd2
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/ParserLiteTest.java
@@ -0,0 +1,191 @@
+// 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import junit.framework.TestCase;
+
+public class ParserLiteTest extends TestCase {
+ 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();
+ assertEquals(message, parser.parseFrom(data, registry));
+ assertEquals(
+ message,
+ parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length, registry));
+ assertEquals(message, parser.parseFrom(message.toByteString(), registry));
+ assertEquals(message, parser.parseFrom(new ByteArrayInputStream(data), registry));
+ assertEquals(message, parser.parseFrom(CodedInputStream.newInstance(data), registry));
+ assertEquals(
+ message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer(), 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();
+ assertEquals(message, parser.parseFrom(data));
+ assertEquals(
+ message, parser.parseFrom(generatePaddingArray(data, offset, padding), offset, length));
+ assertEquals(message, parser.parseFrom(message.toByteString()));
+ assertEquals(message, parser.parseFrom(new ByteArrayInputStream(data)));
+ assertEquals(message, parser.parseFrom(CodedInputStream.newInstance(data)));
+ assertEquals(message, parser.parseFrom(message.toByteString().asReadOnlyByteBuffer()));
+ }
+
+ 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 testParseExtensionsLite() throws Exception {
+ assertRoundTripEquals(
+ TestUtilLite.getAllLiteExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+ }
+
+ public void testParsePacked() throws Exception {
+ assertRoundTripEquals(TestUtil.getPackedSet());
+ assertRoundTripEquals(TestUtil.getPackedExtensionsSet(), TestUtil.getExtensionRegistry());
+ }
+
+ public void testParsePackedLite() throws Exception {
+ assertRoundTripEquals(
+ TestUtilLite.getLitePackedExtensionsSet(), TestUtilLite.getExtensionRegistryLite());
+ }
+
+ public void testParseDelimitedToLite() throws Exception {
+ // Write MessageLite with packed extension fields.
+ TestPackedExtensionsLite packedMessage = TestUtilLite.getLitePackedExtensionsSet();
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ packedMessage.writeDelimitedTo(output);
+ packedMessage.writeDelimitedTo(output);
+
+ InputStream input = new ByteArrayInputStream(output.toByteArray());
+ assertEquals(
+ packedMessage,
+ packedMessage
+ .getParserForType()
+ .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
+ assertEquals(
+ packedMessage,
+ packedMessage
+ .getParserForType()
+ .parseDelimitedFrom(input, TestUtilLite.getExtensionRegistryLite()));
+ }
+
+ /** 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 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.
+ ExtensionRegistryLite registry = ExtensionRegistryLite.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));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java
new file mode 100755
index 000000000..dfda4b3cb
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java
@@ -0,0 +1,171 @@
+// 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.assertNull;
+
+import com.google.protobuf.testing.Proto2Testing;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Proto2ExtensionLookupSchemaTest {
+ private byte[] data;
+ private ExtensionRegistry extensionRegistry;
+
+ @Before
+ public void setup() {
+ TestSchemas.registerGenericProto2Schemas();
+
+ Protobuf.getInstance().schemaFor(Proto2MessageWithExtensions.class);
+ data = new Proto2MessageFactory(10, 20, 1, 1).newMessage().toByteArray();
+ extensionRegistry = ExtensionRegistry.newInstance();
+ Proto2Testing.registerAllExtensions(extensionRegistry);
+ }
+
+ @Test
+ public void testExtensions() throws Exception {
+ Proto2MessageWithExtensions base =
+ Proto2MessageWithExtensions.parseFrom(data, extensionRegistry);
+
+ Proto2MessageWithExtensions message =
+ ExperimentalSerializationUtil.fromByteArray(
+ data, Proto2MessageWithExtensions.class, extensionRegistry);
+ assertEquals(base, message);
+
+ Proto2MessageWithExtensions roundtripMessage =
+ ExperimentalSerializationUtil.fromByteArray(
+ ExperimentalSerializationUtil.toByteArray(message),
+ Proto2MessageWithExtensions.class,
+ extensionRegistry);
+ assertEquals(base, roundtripMessage);
+ }
+
+ @Test
+ public void testUnknownEnum() throws Exception {
+ // Use unknown fields to hold invalid enum values.
+ UnknownFieldSetLite unknowns = UnknownFieldSetLite.newInstance();
+ final int outOfRange = 1000;
+ assertNull(TestEnum.forNumber(outOfRange));
+ unknowns.storeField(
+ WireFormat.makeTag(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.ONE_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) outOfRange);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER, WireFormat.WIRETYPE_VARINT),
+ (long) TestEnum.TWO_VALUE);
+
+ {
+ // Construct a packed enum list.
+ int packedSize =
+ CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE)
+ + CodedOutputStream.computeUInt32SizeNoTag(outOfRange)
+ + CodedOutputStream.computeUInt32SizeNoTag(TestEnum.ONE_VALUE);
+ ByteString.CodedBuilder packedBuilder = ByteString.newCodedBuilder(packedSize);
+ CodedOutputStream packedOut = packedBuilder.getCodedOutput();
+ packedOut.writeEnumNoTag(TestEnum.ONE_VALUE);
+ packedOut.writeEnumNoTag(outOfRange);
+ packedOut.writeEnumNoTag(TestEnum.TWO_VALUE);
+ unknowns.storeField(
+ WireFormat.makeTag(
+ Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER,
+ WireFormat.WIRETYPE_LENGTH_DELIMITED),
+ packedBuilder.build());
+ }
+ int size = unknowns.getSerializedSize();
+ byte[] output = new byte[size];
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ unknowns.writeTo(codedOutput);
+ codedOutput.flush();
+
+ Proto2MessageWithExtensions parsed =
+ ExperimentalSerializationUtil.fromByteArray(
+ output, Proto2MessageWithExtensions.class, extensionRegistry);
+ assertFalse(
+ "out-of-range singular enum should not be in message",
+ parsed.hasExtension(Proto2Testing.fieldEnum13));
+ {
+ List<Long> singularEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_13_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, singularEnum.size());
+ assertEquals((Long) (long) outOfRange, singularEnum.get(0));
+ }
+ {
+ List<Long> repeatedEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_LIST_30_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, repeatedEnum.size());
+ assertEquals((Long) (long) outOfRange, repeatedEnum.get(0));
+ }
+ {
+ List<Long> packedRepeatedEnum =
+ parsed
+ .getUnknownFields()
+ .getField(Proto2Message.FIELD_ENUM_LIST_PACKED_44_FIELD_NUMBER)
+ .getVarintList();
+ assertEquals(1, packedRepeatedEnum.size());
+ assertEquals((Long) (long) outOfRange, packedRepeatedEnum.get(0));
+ }
+ assertEquals(
+ "out-of-range repeated enum should not be in message",
+ 2,
+ parsed.getExtension(Proto2Testing.fieldEnumList30).size());
+ assertEquals(TestEnum.ONE, parsed.getExtension(Proto2Testing.fieldEnumList30, 0));
+ assertEquals(TestEnum.TWO, parsed.getExtension(Proto2Testing.fieldEnumList30, 1));
+ assertEquals(
+ "out-of-range packed repeated enum should not be in message",
+ 2,
+ parsed.getExtension(Proto2Testing.fieldEnumListPacked44).size());
+ assertEquals(TestEnum.ONE, parsed.getExtension(Proto2Testing.fieldEnumListPacked44, 0));
+ assertEquals(TestEnum.TWO, parsed.getExtension(Proto2Testing.fieldEnumListPacked44, 1));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java
new file mode 100755
index 000000000..8242f847e
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Proto2LiteSchemaTest extends AbstractProto2LiteSchemaTest {
+
+ @Override
+ protected Schema<Proto2MessageLite> schema() {
+ return TestSchemasLite.genericProto2LiteSchema;
+ }
+
+ @Override
+ protected void registerSchemas() {
+ TestSchemasLite.registerGenericProto2LiteSchemas();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java
new file mode 100755
index 000000000..b5c61ed99
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java
@@ -0,0 +1,555 @@
+// 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.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Creates instances of {@link Proto2Message} based on the tree configuration. */
+public final class Proto2MessageFactory implements ExperimentalMessageFactory<Proto2Message> {
+ private final int numRepeatedFields;
+ private final int branchingFactor;
+ private final Proto2MessageFactory nextLevel;
+ private final ExperimentalTestDataProvider data;
+
+ public Proto2MessageFactory(
+ int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) {
+ this(
+ new ExperimentalTestDataProvider(stringLength),
+ numRepeatedFields,
+ branchingFactor,
+ treeDepth);
+ }
+
+ private Proto2MessageFactory(
+ ExperimentalTestDataProvider data,
+ int numRepeatedFields,
+ int branchingFactor,
+ int treeDepth) {
+ this.numRepeatedFields = numRepeatedFields;
+ this.branchingFactor = branchingFactor;
+ this.data = data;
+ if (treeDepth > 0) {
+ nextLevel = new Proto2MessageFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1);
+ } else {
+ nextLevel = null;
+ }
+ }
+
+ @Override
+ public ExperimentalTestDataProvider dataProvider() {
+ return data;
+ }
+
+ @Override
+ public Proto2Message newMessage() {
+ Proto2Message.Builder builder = Proto2Message.newBuilder();
+ builder.setFieldDouble1(data.getDouble());
+ builder.setFieldFloat2(data.getFloat());
+ builder.setFieldInt643(data.getLong());
+ builder.setFieldUint644(data.getLong());
+ builder.setFieldInt325(data.getInt());
+ builder.setFieldFixed646(data.getLong());
+ builder.setFieldFixed327(data.getInt());
+ builder.setFieldBool8(data.getBool());
+ builder.setFieldString9(data.getString());
+ // We don't populate the message field. Instead we apply the branching factor to the
+ // repeated message field below.
+ builder.setFieldBytes11(data.getBytes());
+ builder.setFieldUint3212(data.getInt());
+ builder.setFieldEnum13(Proto2Message.TestEnum.forNumber(data.getEnum()));
+ builder.setFieldSfixed3214(data.getInt());
+ builder.setFieldSfixed6415(data.getLong());
+ builder.setFieldSint3216(data.getInt());
+ builder.setFieldSint6417(data.getLong());
+
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ builder.addFieldDoubleList18(data.getDouble());
+ builder.addFieldFloatList19(data.getFloat());
+ builder.addFieldInt64List20(data.getLong());
+ builder.addFieldUint64List21(data.getLong());
+ builder.addFieldInt32List22(data.getInt());
+ builder.addFieldFixed64List23(data.getLong());
+ builder.addFieldFixed32List24(data.getInt());
+ builder.addFieldBoolList25(data.getBool());
+ builder.addFieldStringList26(data.getString());
+ // Repeated message field is controlled by the branching factor below.
+ builder.addFieldBytesList28(data.getBytes());
+ builder.addFieldUint32List29(data.getInt());
+ builder.addFieldEnumList30(Proto2Message.TestEnum.forNumber(data.getEnum()));
+ builder.addFieldSfixed32List31(data.getInt());
+ builder.addFieldSfixed64List32(data.getLong());
+ builder.addFieldSint32List33(data.getInt());
+ builder.addFieldSint64List34(data.getLong());
+
+ builder.addFieldDoubleListPacked35(data.getDouble());
+ builder.addFieldFloatListPacked36(data.getFloat());
+ builder.addFieldInt64ListPacked37(data.getLong());
+ builder.addFieldUint64ListPacked38(data.getLong());
+ builder.addFieldInt32ListPacked39(data.getInt());
+ builder.addFieldFixed64ListPacked40(data.getLong());
+ builder.addFieldFixed32ListPacked41(data.getInt());
+ builder.addFieldBoolListPacked42(data.getBool());
+ builder.addFieldUint32ListPacked43(data.getInt());
+ builder.addFieldEnumListPacked44(Proto2Message.TestEnum.forNumber(data.getEnum()));
+ builder.addFieldSfixed32ListPacked45(data.getInt());
+ builder.addFieldSfixed64ListPacked46(data.getLong());
+ builder.addFieldSint32ListPacked47(data.getInt());
+ builder.addFieldSint64ListPacked48(data.getLong());
+ }
+
+ builder.setFieldGroup49(Proto2Message.FieldGroup49.newBuilder().setFieldInt3250(data.getInt()));
+
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldGroupList51(
+ Proto2Message.FieldGroupList51.newBuilder().setFieldInt3252(data.getInt()));
+ }
+
+ // Set all required fields.
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+
+ // Handle the branching factor.
+ if (nextLevel != null) {
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldMessageList27(nextLevel.newMessage());
+ }
+ }
+
+ return builder.build();
+ }
+
+ private interface MapValueProvider<T> {
+ public T getValue();
+ }
+
+ private final MapValueProvider<Integer> integerProvider =
+ new MapValueProvider<Integer>() {
+ @Override
+ public Integer getValue() {
+ return data.getInt();
+ }
+ };
+ private final MapValueProvider<Long> longProvider =
+ new MapValueProvider<Long>() {
+ @Override
+ public Long getValue() {
+ return data.getLong();
+ }
+ };
+ private final MapValueProvider<String> stringProvider =
+ new MapValueProvider<String>() {
+ @Override
+ public String getValue() {
+ return data.getString();
+ }
+ };
+ private final MapValueProvider<ByteString> bytesProvider =
+ new MapValueProvider<ByteString>() {
+ @Override
+ public ByteString getValue() {
+ return data.getBytes();
+ }
+ };
+ private final MapValueProvider<Boolean> booleanProvider =
+ new MapValueProvider<Boolean>() {
+ @Override
+ public Boolean getValue() {
+ return data.getBool();
+ }
+ };
+ private final MapValueProvider<Float> floatProvider =
+ new MapValueProvider<Float>() {
+ @Override
+ public Float getValue() {
+ return data.getFloat();
+ }
+ };
+ private final MapValueProvider<Double> doubleProvider =
+ new MapValueProvider<Double>() {
+ @Override
+ public Double getValue() {
+ return data.getDouble();
+ }
+ };
+ private final MapValueProvider<Proto2Message> messageProvider =
+ new MapValueProvider<Proto2Message>() {
+ @Override
+ public Proto2Message getValue() {
+ return newMessage();
+ }
+ };
+ private final MapValueProvider<Proto2Message.TestEnum> enumProvider =
+ new MapValueProvider<Proto2Message.TestEnum>() {
+ @Override
+ public Proto2Message.TestEnum getValue() {
+ return Proto2Message.TestEnum.forNumber(data.getEnum());
+ }
+ };
+
+ private <V> Map<Integer, V> populateIntegerMap(MapValueProvider<V> provider) {
+ Map<Integer, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getInt(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Long, V> populateLongMap(MapValueProvider<V> provider) {
+ Map<Long, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getLong(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<String, V> populateStringMap(MapValueProvider<V> provider) {
+ Map<String, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getString(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Boolean, V> populateBooleanMap(MapValueProvider<V> provider) {
+ Map<Boolean, V> map = new HashMap<>();
+ map.put(false, provider.getValue());
+ map.put(true, provider.getValue());
+ return map;
+ }
+
+ public Proto2MessageWithMaps newMessageWithMaps() {
+ Proto2MessageWithMaps.Builder builder = Proto2MessageWithMaps.newBuilder();
+
+ builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider));
+ builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider));
+ builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider));
+ builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider));
+ builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider));
+ builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider));
+ builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider));
+ builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider));
+ builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider));
+ builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider));
+ builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider));
+ builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider));
+ builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider));
+ builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider));
+ builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider));
+ builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider));
+ builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider));
+ builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider));
+ builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider));
+ builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider));
+ builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider));
+ builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider));
+ builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64String83(populateLongMap(stringProvider));
+ builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider));
+ builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider));
+ builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider));
+ builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider));
+ builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider));
+ builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider));
+ builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider));
+ builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider));
+ builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64String151(populateLongMap(stringProvider));
+ builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider));
+ builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider));
+ builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider));
+ builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider));
+ builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider));
+ builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider));
+ builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider));
+ builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringInt64162(populateStringMap(longProvider));
+ builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider));
+ builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider));
+ builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSint64167(populateStringMap(longProvider));
+ builder.putAllFieldMapStringString168(populateStringMap(stringProvider));
+ builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringUint64170(populateStringMap(longProvider));
+ builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider));
+ builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider));
+ builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider));
+ builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider));
+ builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider));
+ builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider));
+ builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64String202(populateLongMap(stringProvider));
+ builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider));
+
+ return builder.build();
+ }
+
+ public List<Proto2Message> newMessagesMissingRequiredFields() {
+ List<Proto2Message> results = new ArrayList<>();
+ for (int i = 71; i <= 88; ++i) {
+ Proto2Message.Builder builder = Proto2Message.newBuilder();
+ populateRequiredFields(builder, i);
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested optional message field is missing required fields.
+ Proto2Message.Builder builder = Proto2Message.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.setFieldMessage10(Proto2Message.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested repeated message field is missing required fields.
+ Proto2Message.Builder builder = Proto2Message.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.addFieldMessageList27(Proto2Message.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested oneof message field is missing required fields.
+ Proto2Message.Builder builder = Proto2Message.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.setFieldMessage62(Proto2Message.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ return results;
+ }
+
+ // 0 is not a valid field number so we use it to mean no fields are excluded.
+ private static final int INCLUDE_ALL_REQUIRED_FIELDS = 0;
+
+ private void populateRequiredFields(Proto2Message.Builder builder, int excludedFieldNumber) {
+ if (excludedFieldNumber != 71) {
+ builder.setFieldRequiredDouble71(data.getDouble());
+ }
+ if (excludedFieldNumber != 72) {
+ builder.setFieldRequiredFloat72(data.getFloat());
+ }
+ if (excludedFieldNumber != 73) {
+ builder.setFieldRequiredInt6473(data.getLong());
+ }
+ if (excludedFieldNumber != 74) {
+ builder.setFieldRequiredUint6474(data.getLong());
+ }
+ if (excludedFieldNumber != 75) {
+ builder.setFieldRequiredInt3275(data.getInt());
+ }
+ if (excludedFieldNumber != 76) {
+ builder.setFieldRequiredFixed6476(data.getLong());
+ }
+ if (excludedFieldNumber != 77) {
+ builder.setFieldRequiredFixed3277(data.getInt());
+ }
+ if (excludedFieldNumber != 78) {
+ builder.setFieldRequiredBool78(data.getBool());
+ }
+ if (excludedFieldNumber != 79) {
+ builder.setFieldRequiredString79(data.getString());
+ }
+ if (excludedFieldNumber != 80) {
+ builder.setFieldRequiredMessage80(
+ Proto2Message.RequiredNestedMessage.newBuilder().setValue(data.getInt()));
+ }
+ if (excludedFieldNumber != 81) {
+ builder.setFieldRequiredBytes81(data.getBytes());
+ }
+ if (excludedFieldNumber != 82) {
+ builder.setFieldRequiredUint3282(data.getInt());
+ }
+ if (excludedFieldNumber != 83) {
+ builder.setFieldRequiredEnum83(Proto2Message.TestEnum.forNumber(data.getEnum()));
+ }
+ if (excludedFieldNumber != 84) {
+ builder.setFieldRequiredSfixed3284(data.getInt());
+ }
+ if (excludedFieldNumber != 85) {
+ builder.setFieldRequiredSfixed6485(data.getLong());
+ }
+ if (excludedFieldNumber != 86) {
+ builder.setFieldRequiredSint3286(data.getInt());
+ }
+ if (excludedFieldNumber != 87) {
+ builder.setFieldRequiredSint6487(data.getLong());
+ }
+ if (excludedFieldNumber != 88) {
+ builder.setFieldRequiredGroup88(
+ Proto2Message.FieldRequiredGroup88.newBuilder().setFieldInt3289(data.getInt()));
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java
new file mode 100755
index 000000000..af671b22e
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageInfoFactory.java
@@ -0,0 +1,892 @@
+// 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.FieldInfo.forField;
+import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier;
+import static com.google.protobuf.FieldInfo.forMapField;
+import static com.google.protobuf.FieldInfo.forOneofMemberField;
+import static com.google.protobuf.FieldInfo.forProto2OptionalField;
+import static com.google.protobuf.FieldInfo.forProto2RequiredField;
+import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
+
+import com.google.protobuf.testing.Proto2Testing;
+import com.google.protobuf.testing.Proto2Testing.Proto2Empty;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroup49;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroup69;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldGroupList51;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.FieldRequiredGroup88;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.RequiredNestedMessage;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message.TestEnum;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps;
+import java.lang.reflect.Field;
+
+/** A factory that generates a hard-coded message info for {@link Proto2Message}. */
+public final class Proto2MessageInfoFactory implements MessageInfoFactory {
+ private static final Proto2MessageInfoFactory INSTANCE = new Proto2MessageInfoFactory();
+
+ private Proto2MessageInfoFactory() {}
+
+ public static Proto2MessageInfoFactory getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ return true;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ if (Proto2Message.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2Message();
+ } else if (FieldGroup49.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroup49();
+ } else if (FieldGroupList51.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroupList51();
+ } else if (FieldGroup69.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroup69();
+ } else if (FieldRequiredGroup88.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldRequiredGroup88();
+ } else if (RequiredNestedMessage.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForRequiredNestedMessage();
+ } else if (Proto2Empty.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2Empty();
+ } else if (Proto2MessageWithExtensions.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2MessageWithExtensions();
+ } else if (Proto2Testing.FieldGroup49.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForExtensionFieldGroup49();
+ } else if (Proto2Testing.FieldGroupList51.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForExtensionFieldGroupList51();
+ } else if (Proto2Testing.Proto2MessageWithMaps.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2MessageWithMaps();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ /**
+ * Creates a new hard-coded info for {@link Proto2Message}. Each time this is called, we manually
+ * go through the entire process of what a message would do if it self-registered its own info,
+ * including looking up each field by name. This is done for benchmarking purposes, so that we get
+ * a more accurate representation of the time it takes to perform this process.
+ */
+ private static StructuralMessageInfo newMessageInfoForProto2Message() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(50);
+ builder.withCheckInitialized(
+ new int[] {
+ 10, 27, 62, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ });
+ lookupFieldsByName(builder);
+ return builder.build();
+ }
+
+ private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) {
+ Field bitField0 = field("bitField0_");
+
+ builder.withDefaultInstance(Proto2Message.getDefaultInstance());
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldDouble1_"), 1, FieldType.DOUBLE, bitField0, 0x00000001, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldFloat2_"), 2, FieldType.FLOAT, bitField0, 0x00000002, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldInt643_"), 3, FieldType.INT64, bitField0, 0x00000004, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldUint644_"), 4, FieldType.UINT64, bitField0, 0x00000008, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldInt325_"), 5, FieldType.INT32, bitField0, 0x00000010, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldFixed646_"), 6, FieldType.FIXED64, bitField0, 0x00000020, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldFixed327_"), 7, FieldType.FIXED32, bitField0, 0x00000040, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldBool8_"), 8, FieldType.BOOL, bitField0, 0x00000080, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldString9_"), 9, FieldType.STRING, bitField0, 0x00000100, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldMessage10_"), 10, FieldType.MESSAGE, bitField0, 0x00000200, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldBytes11_"), 11, FieldType.BYTES, bitField0, 0x00000400, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldUint3212_"), 12, FieldType.UINT32, bitField0, 0x00000800, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldEnum13_"),
+ 13,
+ FieldType.ENUM,
+ bitField0,
+ 0x00001000,
+ false,
+ asVerifier(TestEnum.internalGetValueMap())));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldSfixed3214_"), 14, FieldType.SFIXED32, bitField0, 0x00002000, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldSfixed6415_"), 15, FieldType.SFIXED64, bitField0, 0x00004000, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldSint3216_"), 16, FieldType.SINT32, bitField0, 0x00008000, false, null));
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldSint6417_"), 17, FieldType.SINT64, bitField0, 0x00010000, false, null));
+ builder.withField(forField(field("fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, false));
+ builder.withField(forField(field("fieldFloatList19_"), 19, FieldType.FLOAT_LIST, false));
+ builder.withField(forField(field("fieldInt64List20_"), 20, FieldType.INT64_LIST, false));
+ builder.withField(forField(field("fieldUint64List21_"), 21, FieldType.UINT64_LIST, false));
+ builder.withField(forField(field("fieldInt32List22_"), 22, FieldType.INT32_LIST, false));
+ builder.withField(forField(field("fieldFixed64List23_"), 23, FieldType.FIXED64_LIST, false));
+ builder.withField(forField(field("fieldFixed32List24_"), 24, FieldType.FIXED32_LIST, false));
+ builder.withField(forField(field("fieldBoolList25_"), 25, FieldType.BOOL_LIST, false));
+ builder.withField(forField(field("fieldStringList26_"), 26, FieldType.STRING_LIST, false));
+ builder.withField(
+ forRepeatedMessageField(
+ field("fieldMessageList27_"), 27, FieldType.MESSAGE_LIST, Proto2Message.class));
+ builder.withField(forField(field("fieldBytesList28_"), 28, FieldType.BYTES_LIST, false));
+ builder.withField(forField(field("fieldUint32List29_"), 29, FieldType.UINT32_LIST, false));
+ builder.withField(
+ forFieldWithEnumVerifier(
+ field("fieldEnumList30_"),
+ 30,
+ FieldType.ENUM_LIST,
+ asVerifier(TestEnum.internalGetValueMap())));
+ builder.withField(forField(field("fieldSfixed32List31_"), 31, FieldType.SFIXED32_LIST, false));
+ builder.withField(forField(field("fieldSfixed64List32_"), 32, FieldType.SFIXED64_LIST, false));
+ builder.withField(forField(field("fieldSint32List33_"), 33, FieldType.SINT32_LIST, false));
+ builder.withField(forField(field("fieldSint64List34_"), 34, FieldType.SINT64_LIST, false));
+ builder.withField(
+ forField(field("fieldDoubleListPacked35_"), 35, FieldType.DOUBLE_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldFloatListPacked36_"), 36, FieldType.FLOAT_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldInt64ListPacked37_"), 37, FieldType.INT64_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldUint64ListPacked38_"), 38, FieldType.UINT64_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldInt32ListPacked39_"), 39, FieldType.INT32_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldFixed64ListPacked40_"), 40, FieldType.FIXED64_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldFixed32ListPacked41_"), 41, FieldType.FIXED32_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldBoolListPacked42_"), 42, FieldType.BOOL_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldUint32ListPacked43_"), 43, FieldType.UINT32_LIST_PACKED, false));
+ builder.withField(
+ forFieldWithEnumVerifier(
+ field("fieldEnumListPacked44_"),
+ 44,
+ FieldType.ENUM_LIST_PACKED,
+ asVerifier(TestEnum.internalGetValueMap())));
+ builder.withField(
+ forField(field("fieldSfixed32ListPacked45_"), 45, FieldType.SFIXED32_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldSfixed64ListPacked46_"), 46, FieldType.SFIXED64_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldSint32ListPacked47_"), 47, FieldType.SINT32_LIST_PACKED, false));
+ builder.withField(
+ forField(field("fieldSint64ListPacked48_"), 48, FieldType.SINT64_LIST_PACKED, false));
+
+ builder.withField(
+ forProto2OptionalField(
+ field("fieldGroup49_"), 49, FieldType.GROUP, bitField0, 0x00020000, false, null));
+ builder.withField(
+ forRepeatedMessageField(
+ field("fieldGroupList51_"),
+ 51,
+ FieldType.GROUP_LIST,
+ Proto2Message.FieldGroupList51.class));
+
+ OneofInfo oneof = new OneofInfo(0, field("testOneofCase_"), field("testOneof_"));
+ builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, false, null));
+ builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, false, null));
+ builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, false, null));
+ builder.withField(
+ forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, false, null));
+ builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, false, null));
+ builder.withField(
+ forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto2Message.class, false, null));
+ builder.withField(
+ forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, false, null));
+ builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, false, null));
+ builder.withField(
+ forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, false, null));
+ builder.withField(
+ forOneofMemberField(
+ 69, FieldType.GROUP, oneof, Proto2Message.FieldGroup69.class, false, null));
+
+ Field bitField1 = field("bitField1_");
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredDouble71_"),
+ 71,
+ FieldType.DOUBLE,
+ bitField1,
+ 0x00000008,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredFloat72_"),
+ 72,
+ FieldType.FLOAT,
+ bitField1,
+ 0x00000010,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredInt6473_"),
+ 73,
+ FieldType.INT64,
+ bitField1,
+ 0x00000020,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredUint6474_"),
+ 74,
+ FieldType.UINT64,
+ bitField1,
+ 0x00000040,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredInt3275_"),
+ 75,
+ FieldType.INT32,
+ bitField1,
+ 0x00000080,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredFixed6476_"),
+ 76,
+ FieldType.FIXED64,
+ bitField1,
+ 0x00000100,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredFixed3277_"),
+ 77,
+ FieldType.FIXED32,
+ bitField1,
+ 0x00000200,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredBool78_"), 78, FieldType.BOOL, bitField1, 0x00000400, false, null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredString79_"),
+ 79,
+ FieldType.STRING,
+ bitField1,
+ 0x00000800,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredMessage80_"),
+ 80,
+ FieldType.MESSAGE,
+ bitField1,
+ 0x00001000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredBytes81_"),
+ 81,
+ FieldType.BYTES,
+ bitField1,
+ 0x00002000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredUint3282_"),
+ 82,
+ FieldType.UINT32,
+ bitField1,
+ 0x00004000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredEnum83_"),
+ 83,
+ FieldType.ENUM,
+ bitField1,
+ 0x00008000,
+ false,
+ asVerifier(TestEnum.internalGetValueMap())));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredSfixed3284_"),
+ 84,
+ FieldType.SFIXED32,
+ bitField1,
+ 0x00010000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredSfixed6485_"),
+ 85,
+ FieldType.SFIXED64,
+ bitField1,
+ 0x00020000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredSint3286_"),
+ 86,
+ FieldType.SINT32,
+ bitField1,
+ 0x00040000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredSint6487_"),
+ 87,
+ FieldType.SINT64,
+ bitField1,
+ 0x00080000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field("fieldRequiredGroup88_"),
+ 88,
+ FieldType.GROUP,
+ bitField1,
+ 0x00100000,
+ false,
+ null));
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroup49() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroup49.class, "fieldInt3250_"),
+ 50,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroupList51() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroupList51.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroupList51.class, "fieldInt3252_"),
+ 52,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroup69() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroup69.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroup69.class, "fieldInt3270_"),
+ 70,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForRequiredNestedMessage() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(RequiredNestedMessage.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(RequiredNestedMessage.class, "value_"),
+ 1,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldRequiredGroup88() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldRequiredGroup88.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldRequiredGroup88.class, "fieldInt3289_"),
+ 89,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto2Empty() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto2MessageWithExtensions() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(0);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForExtensionFieldGroup49() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(Proto2Testing.FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2Testing.FieldGroup49.class, "fieldInt3250_"),
+ 50,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForExtensionFieldGroupList51() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(Proto2Testing.FieldGroupList51.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2Testing.FieldGroupList51.class, "fieldInt3252_"),
+ 52,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto2MessageWithMaps() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder();
+ builder.withCheckInitialized(
+ new int[] {
+ 10, 27, 44, 61, 78, 95, 112, 129, 146, 163, 180, 197,
+ });
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_bool_1", 1));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_bytes_2", 2));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_double_3", 3));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_enum_4", 4));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_fixed32_5", 5));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_fixed64_6", 6));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_float_7", 7));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_int32_8", 8));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_int64_9", 9));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_message_10", 10));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sfixed32_11", 11));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sfixed64_12", 12));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sint32_13", 13));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_sint64_14", 14));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_string_15", 15));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_uint32_16", 16));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_bool_uint64_17", 17));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_bool_18", 18));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_bytes_19", 19));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_double_20", 20));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_enum_21", 21));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_fixed32_22", 22));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_fixed64_23", 23));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_float_24", 24));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_int32_25", 25));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_int64_26", 26));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_message_27", 27));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sfixed32_28", 28));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sfixed64_29", 29));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sint32_30", 30));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_sint64_31", 31));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_string_32", 32));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_uint32_33", 33));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed32_uint64_34", 34));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_bool_35", 35));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_bytes_36", 36));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_double_37", 37));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_enum_38", 38));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_fixed32_39", 39));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_fixed64_40", 40));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_float_41", 41));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_int32_42", 42));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_int64_43", 43));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_message_44", 44));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sfixed32_45", 45));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sfixed64_46", 46));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sint32_47", 47));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_sint64_48", 48));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_string_49", 49));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_uint32_50", 50));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_fixed64_uint64_51", 51));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_bool_52", 52));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_bytes_53", 53));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_double_54", 54));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_enum_55", 55));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_fixed32_56", 56));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_fixed64_57", 57));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_float_58", 58));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_int32_59", 59));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_int64_60", 60));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_message_61", 61));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sfixed32_62", 62));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sfixed64_63", 63));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sint32_64", 64));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_sint64_65", 65));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_string_66", 66));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_uint32_67", 67));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int32_uint64_68", 68));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_bool_69", 69));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_bytes_70", 70));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_double_71", 71));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_enum_72", 72));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_fixed32_73", 73));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_fixed64_74", 74));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_float_75", 75));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_int32_76", 76));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_int64_77", 77));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_message_78", 78));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sfixed32_79", 79));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sfixed64_80", 80));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sint32_81", 81));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_sint64_82", 82));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_string_83", 83));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_uint32_84", 84));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_int64_uint64_85", 85));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_bool_86", 86));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_bytes_87", 87));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_double_88", 88));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_enum_89", 89));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_fixed32_90", 90));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_fixed64_91", 91));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_float_92", 92));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_int32_93", 93));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_int64_94", 94));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_message_95", 95));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sfixed32_96", 96));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sfixed64_97", 97));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sint32_98", 98));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_sint64_99", 99));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_string_100", 100));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_uint32_101", 101));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed32_uint64_102", 102));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_bool_103", 103));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_bytes_104", 104));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_double_105", 105));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_enum_106", 106));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_fixed32_107", 107));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_fixed64_108", 108));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_float_109", 109));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_int32_110", 110));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_int64_111", 111));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_message_112", 112));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sfixed32_113", 113));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sfixed64_114", 114));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sint32_115", 115));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_sint64_116", 116));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_string_117", 117));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_uint32_118", 118));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sfixed64_uint64_119", 119));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_bool_120", 120));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_bytes_121", 121));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_double_122", 122));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_enum_123", 123));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_fixed32_124", 124));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_fixed64_125", 125));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_float_126", 126));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_int32_127", 127));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_int64_128", 128));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_message_129", 129));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sfixed32_130", 130));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sfixed64_131", 131));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sint32_132", 132));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_sint64_133", 133));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_string_134", 134));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_uint32_135", 135));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint32_uint64_136", 136));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_bool_137", 137));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_bytes_138", 138));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_double_139", 139));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_enum_140", 140));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_fixed32_141", 141));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_fixed64_142", 142));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_float_143", 143));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_int32_144", 144));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_int64_145", 145));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_message_146", 146));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sfixed32_147", 147));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sfixed64_148", 148));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sint32_149", 149));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_sint64_150", 150));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_string_151", 151));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_uint32_152", 152));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_sint64_uint64_153", 153));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_bool_154", 154));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_bytes_155", 155));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_double_156", 156));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_enum_157", 157));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_fixed32_158", 158));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_fixed64_159", 159));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_float_160", 160));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_int32_161", 161));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_int64_162", 162));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_message_163", 163));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sfixed32_164", 164));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sfixed64_165", 165));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sint32_166", 166));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_sint64_167", 167));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_string_168", 168));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_uint32_169", 169));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_string_uint64_170", 170));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_bool_171", 171));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_bytes_172", 172));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_double_173", 173));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_enum_174", 174));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_fixed32_175", 175));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_fixed64_176", 176));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_float_177", 177));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_int32_178", 178));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_int64_179", 179));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_message_180", 180));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sfixed32_181", 181));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sfixed64_182", 182));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sint32_183", 183));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_sint64_184", 184));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_string_185", 185));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_uint32_186", 186));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint32_uint64_187", 187));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_bool_188", 188));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_bytes_189", 189));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_double_190", 190));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_enum_191", 191));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_fixed32_192", 192));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_fixed64_193", 193));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_float_194", 194));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_int32_195", 195));
+ builder.withField(mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_int64_196", 196));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_message_197", 197));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sfixed32_198", 198));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sfixed64_199", 199));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sint32_200", 200));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_sint64_201", 201));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_string_202", 202));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint32_203", 203));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint64_204", 204));
+
+ return builder.build();
+ }
+
+ private static FieldInfo mapFieldInfo(Class<?> clazz, String fieldName, int fieldNumber) {
+ try {
+ return forMapField(
+ field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"),
+ fieldNumber,
+ SchemaUtil.getMapDefaultEntry(clazz, fieldName),
+ fieldName.contains("_enum_") ? asVerifier(TestEnum.internalGetValueMap()) : null);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+
+ private static Field field(String name) {
+ return field(Proto2Message.class, name);
+ }
+
+ private static Field field(Class<?> clazz, String name) {
+ try {
+ return clazz.getDeclaredField(name);
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static Internal.EnumVerifier asVerifier(final Internal.EnumLiteMap<?> map) {
+ return new Internal.EnumVerifier() {
+ @Override
+ public boolean isInRange(int number) {
+ return map.findValueByNumber(number) != null;
+ }
+ };
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java b/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java
new file mode 100755
index 000000000..2da349424
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java
@@ -0,0 +1,558 @@
+// 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.testing.Proto2TestingLite.Proto2MessageLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Creates instances of {@link Proto2MessageLite} based on the tree configuration. */
+public final class Proto2MessageLiteFactory
+ implements ExperimentalMessageFactory<Proto2MessageLite> {
+ private final int numRepeatedFields;
+ private final int branchingFactor;
+ private final Proto2MessageLiteFactory nextLevel;
+ private final ExperimentalTestDataProvider data;
+
+ public Proto2MessageLiteFactory(
+ int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) {
+ this(
+ new ExperimentalTestDataProvider(stringLength),
+ numRepeatedFields,
+ branchingFactor,
+ treeDepth);
+ }
+
+ private Proto2MessageLiteFactory(
+ ExperimentalTestDataProvider data,
+ int numRepeatedFields,
+ int branchingFactor,
+ int treeDepth) {
+ this.numRepeatedFields = numRepeatedFields;
+ this.branchingFactor = branchingFactor;
+ this.data = data;
+ if (treeDepth > 0) {
+ nextLevel =
+ new Proto2MessageLiteFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1);
+ } else {
+ nextLevel = null;
+ }
+ }
+
+ @Override
+ public ExperimentalTestDataProvider dataProvider() {
+ return data;
+ }
+
+ @Override
+ public Proto2MessageLite newMessage() {
+ Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder();
+ builder.setFieldDouble1(data.getDouble());
+ builder.setFieldFloat2(data.getFloat());
+ builder.setFieldInt643(data.getLong());
+ builder.setFieldUint644(data.getLong());
+ builder.setFieldInt325(data.getInt());
+ builder.setFieldFixed646(data.getLong());
+ builder.setFieldFixed327(data.getInt());
+ builder.setFieldBool8(data.getBool());
+ builder.setFieldString9(data.getString());
+ // We don't populate the message field. Instead we apply the branching factor to the
+ // repeated message field below.
+ builder.setFieldBytes11(data.getBytes());
+ builder.setFieldUint3212(data.getInt());
+ builder.setFieldEnum13(Proto2MessageLite.TestEnum.forNumber(data.getEnum()));
+ builder.setFieldSfixed3214(data.getInt());
+ builder.setFieldSfixed6415(data.getLong());
+ builder.setFieldSint3216(data.getInt());
+ builder.setFieldSint6417(data.getLong());
+
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ builder.addFieldDoubleList18(data.getDouble());
+ builder.addFieldFloatList19(data.getFloat());
+ builder.addFieldInt64List20(data.getLong());
+ builder.addFieldUint64List21(data.getLong());
+ builder.addFieldInt32List22(data.getInt());
+ builder.addFieldFixed64List23(data.getLong());
+ builder.addFieldFixed32List24(data.getInt());
+ builder.addFieldBoolList25(data.getBool());
+ builder.addFieldStringList26(data.getString());
+ // Repeated message field is controlled by the branching factor below.
+ builder.addFieldBytesList28(data.getBytes());
+ builder.addFieldUint32List29(data.getInt());
+ builder.addFieldEnumList30(Proto2MessageLite.TestEnum.forNumber(data.getEnum()));
+ builder.addFieldSfixed32List31(data.getInt());
+ builder.addFieldSfixed64List32(data.getLong());
+ builder.addFieldSint32List33(data.getInt());
+ builder.addFieldSint64List34(data.getLong());
+
+ builder.addFieldDoubleListPacked35(data.getDouble());
+ builder.addFieldFloatListPacked36(data.getFloat());
+ builder.addFieldInt64ListPacked37(data.getLong());
+ builder.addFieldUint64ListPacked38(data.getLong());
+ builder.addFieldInt32ListPacked39(data.getInt());
+ builder.addFieldFixed64ListPacked40(data.getLong());
+ builder.addFieldFixed32ListPacked41(data.getInt());
+ builder.addFieldBoolListPacked42(data.getBool());
+ builder.addFieldUint32ListPacked43(data.getInt());
+ builder.addFieldEnumListPacked44(Proto2MessageLite.TestEnum.forNumber(data.getEnum()));
+ builder.addFieldSfixed32ListPacked45(data.getInt());
+ builder.addFieldSfixed64ListPacked46(data.getLong());
+ builder.addFieldSint32ListPacked47(data.getInt());
+ builder.addFieldSint64ListPacked48(data.getLong());
+ }
+
+ builder.setFieldGroup49(
+ Proto2MessageLite.FieldGroup49.newBuilder().setFieldInt3250(data.getInt()));
+
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldGroupList51(
+ Proto2MessageLite.FieldGroupList51.newBuilder().setFieldInt3252(data.getInt()));
+ }
+
+ // Set all required fields.
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+
+ // Handle the branching factor.
+ if (nextLevel != null) {
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldMessageList27(nextLevel.newMessage());
+ }
+ }
+
+ return builder.build();
+ }
+
+ private interface MapValueProvider<T> {
+ public T getValue();
+ }
+
+ private final MapValueProvider<Integer> integerProvider =
+ new MapValueProvider<Integer>() {
+ @Override
+ public Integer getValue() {
+ return data.getInt();
+ }
+ };
+ private final MapValueProvider<Long> longProvider =
+ new MapValueProvider<Long>() {
+ @Override
+ public Long getValue() {
+ return data.getLong();
+ }
+ };
+ private final MapValueProvider<String> stringProvider =
+ new MapValueProvider<String>() {
+ @Override
+ public String getValue() {
+ return data.getString();
+ }
+ };
+ private final MapValueProvider<ByteString> bytesProvider =
+ new MapValueProvider<ByteString>() {
+ @Override
+ public ByteString getValue() {
+ return data.getBytes();
+ }
+ };
+ private final MapValueProvider<Boolean> booleanProvider =
+ new MapValueProvider<Boolean>() {
+ @Override
+ public Boolean getValue() {
+ return data.getBool();
+ }
+ };
+ private final MapValueProvider<Float> floatProvider =
+ new MapValueProvider<Float>() {
+ @Override
+ public Float getValue() {
+ return data.getFloat();
+ }
+ };
+ private final MapValueProvider<Double> doubleProvider =
+ new MapValueProvider<Double>() {
+ @Override
+ public Double getValue() {
+ return data.getDouble();
+ }
+ };
+ private final MapValueProvider<Proto2MessageLite> messageProvider =
+ new MapValueProvider<Proto2MessageLite>() {
+ @Override
+ public Proto2MessageLite getValue() {
+ return newMessage();
+ }
+ };
+ private final MapValueProvider<Proto2MessageLite.TestEnum> enumProvider =
+ new MapValueProvider<Proto2MessageLite.TestEnum>() {
+ @Override
+ public Proto2MessageLite.TestEnum getValue() {
+ return Proto2MessageLite.TestEnum.forNumber(data.getEnum());
+ }
+ };
+
+ private <V> Map<Integer, V> populateIntegerMap(MapValueProvider<V> provider) {
+ Map<Integer, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getInt(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Long, V> populateLongMap(MapValueProvider<V> provider) {
+ Map<Long, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getLong(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<String, V> populateStringMap(MapValueProvider<V> provider) {
+ Map<String, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getString(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Boolean, V> populateBooleanMap(MapValueProvider<V> provider) {
+ Map<Boolean, V> map = new HashMap<>();
+ map.put(false, provider.getValue());
+ map.put(true, provider.getValue());
+ return map;
+ }
+
+ public Proto2MessageLiteWithMaps newMessageWithMaps() {
+ Proto2MessageLiteWithMaps.Builder builder = Proto2MessageLiteWithMaps.newBuilder();
+
+ builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider));
+ builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider));
+ builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider));
+ builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider));
+ builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider));
+ builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider));
+ builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider));
+ builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider));
+ builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider));
+ builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider));
+ builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider));
+ builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider));
+ builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider));
+ builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider));
+ builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider));
+ builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider));
+ builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider));
+ builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider));
+ builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider));
+ builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider));
+ builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider));
+ builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider));
+ builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64String83(populateLongMap(stringProvider));
+ builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider));
+ builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider));
+ builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider));
+ builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider));
+ builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider));
+ builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider));
+ builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider));
+ builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider));
+ builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64String151(populateLongMap(stringProvider));
+ builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider));
+ builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider));
+ builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider));
+ builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider));
+ builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider));
+ builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider));
+ builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider));
+ builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringInt64162(populateStringMap(longProvider));
+ builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider));
+ builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider));
+ builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSint64167(populateStringMap(longProvider));
+ builder.putAllFieldMapStringString168(populateStringMap(stringProvider));
+ builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringUint64170(populateStringMap(longProvider));
+ builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider));
+ builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider));
+ builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider));
+ builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider));
+ builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider));
+ builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider));
+ builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64String202(populateLongMap(stringProvider));
+ builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider));
+
+ return builder.build();
+ }
+
+ public List<Proto2MessageLite> newMessagesMissingRequiredFields() {
+ List<Proto2MessageLite> results = new ArrayList<>();
+ for (int i = 71; i <= 88; ++i) {
+ Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder();
+ populateRequiredFields(builder, i);
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested optional message field is missing required fields.
+ Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.setFieldMessage10(Proto2MessageLite.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested repeated message field is missing required fields.
+ Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.addFieldMessageList27(Proto2MessageLite.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ {
+ // A nested oneof message field is missing required fields.
+ Proto2MessageLite.Builder builder = Proto2MessageLite.newBuilder();
+ populateRequiredFields(builder, INCLUDE_ALL_REQUIRED_FIELDS);
+ builder.setFieldMessage62(Proto2MessageLite.getDefaultInstance());
+ results.add(builder.buildPartial());
+ }
+ return results;
+ }
+
+ // 0 is not a valid field number so we use it to mean no fields are excluded.
+ private static final int INCLUDE_ALL_REQUIRED_FIELDS = 0;
+
+ private void populateRequiredFields(Proto2MessageLite.Builder builder, int excludedFieldNumber) {
+ if (excludedFieldNumber != 71) {
+ builder.setFieldRequiredDouble71(data.getDouble());
+ }
+ if (excludedFieldNumber != 72) {
+ builder.setFieldRequiredFloat72(data.getFloat());
+ }
+ if (excludedFieldNumber != 73) {
+ builder.setFieldRequiredInt6473(data.getLong());
+ }
+ if (excludedFieldNumber != 74) {
+ builder.setFieldRequiredUint6474(data.getLong());
+ }
+ if (excludedFieldNumber != 75) {
+ builder.setFieldRequiredInt3275(data.getInt());
+ }
+ if (excludedFieldNumber != 76) {
+ builder.setFieldRequiredFixed6476(data.getLong());
+ }
+ if (excludedFieldNumber != 77) {
+ builder.setFieldRequiredFixed3277(data.getInt());
+ }
+ if (excludedFieldNumber != 78) {
+ builder.setFieldRequiredBool78(data.getBool());
+ }
+ if (excludedFieldNumber != 79) {
+ builder.setFieldRequiredString79(data.getString());
+ }
+ if (excludedFieldNumber != 80) {
+ builder.setFieldRequiredMessage80(
+ Proto2MessageLite.RequiredNestedMessage.newBuilder().setValue(data.getInt()));
+ }
+ if (excludedFieldNumber != 81) {
+ builder.setFieldRequiredBytes81(data.getBytes());
+ }
+ if (excludedFieldNumber != 82) {
+ builder.setFieldRequiredUint3282(data.getInt());
+ }
+ if (excludedFieldNumber != 83) {
+ builder.setFieldRequiredEnum83(Proto2MessageLite.TestEnum.forNumber(data.getEnum()));
+ }
+ if (excludedFieldNumber != 84) {
+ builder.setFieldRequiredSfixed3284(data.getInt());
+ }
+ if (excludedFieldNumber != 85) {
+ builder.setFieldRequiredSfixed6485(data.getLong());
+ }
+ if (excludedFieldNumber != 86) {
+ builder.setFieldRequiredSint3286(data.getInt());
+ }
+ if (excludedFieldNumber != 87) {
+ builder.setFieldRequiredSint6487(data.getLong());
+ }
+ if (excludedFieldNumber != 88) {
+ builder.setFieldRequiredGroup88(
+ Proto2MessageLite.FieldRequiredGroup88.newBuilder().setFieldInt3289(data.getInt()));
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java
new file mode 100755
index 000000000..098e7fe18
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Proto2SchemaTest extends AbstractProto2SchemaTest {
+
+ @Override
+ protected Schema<Proto2Message> schema() {
+ return TestSchemas.genericProto2Schema;
+ }
+
+ @Override
+ protected void registerSchemas() {
+ TestSchemas.registerGenericProto2Schemas();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java
new file mode 100755
index 000000000..57ac0695e
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java
@@ -0,0 +1,111 @@
+// 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.UnittestProto;
+import protobuf_unittest.UnittestProto.TestAllExtensions;
+import protobuf_unittest.UnittestProto.TestAllTypes;
+import junit.framework.TestCase;
+
+/** Unit tests for proto2 that treats unknown enum values as unknown fields. */
+public class Proto2UnknownEnumValueTest extends TestCase {
+ FieldDescriptor singularField =
+ TestAllTypes.getDescriptor().findFieldByName("optional_nested_enum");
+ FieldDescriptor repeatedField =
+ TestAllTypes.getDescriptor().findFieldByName("repeated_nested_enum");
+ byte[] payload = buildPayloadWithUnknownEnumValues();
+
+ private byte[] buildPayloadWithUnknownEnumValues() {
+ // Builds a payload with unknown enum values.
+ UnknownFieldSet.Builder builder = UnknownFieldSet.newBuilder();
+ builder.addField(
+ singularField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.BAR.getNumber())
+ .addVarint(1901 /* unknown enum value */)
+ .build());
+ builder.addField(
+ repeatedField.getNumber(),
+ UnknownFieldSet.Field.newBuilder()
+ .addVarint(TestAllTypes.NestedEnum.FOO.getNumber())
+ .addVarint(1902 /* unknown enum value */)
+ .addVarint(TestAllTypes.NestedEnum.BAZ.getNumber())
+ .addVarint(1903 /* unknown enum value */)
+ .build());
+ return builder.build().toByteArray();
+ }
+
+ public void testUnknownEnumValues() throws Exception {
+ TestAllTypes message = TestAllTypes.parseFrom(payload);
+
+ // Known enum values should be preserved.
+ assertEquals(TestAllTypes.NestedEnum.BAR, message.getOptionalNestedEnum());
+ assertEquals(2, message.getRepeatedNestedEnumList().size());
+ assertEquals(TestAllTypes.NestedEnum.FOO, message.getRepeatedNestedEnum(0));
+ assertEquals(TestAllTypes.NestedEnum.BAZ, message.getRepeatedNestedEnum(1));
+
+ // Unknown enum values should be found in UnknownFieldSet.
+ UnknownFieldSet unknown = message.getUnknownFields();
+ assertEquals(
+ 1901, unknown.getField(singularField.getNumber()).getVarintList().get(0).longValue());
+ assertEquals(
+ 1902, unknown.getField(repeatedField.getNumber()).getVarintList().get(0).longValue());
+ assertEquals(
+ 1903, unknown.getField(repeatedField.getNumber()).getVarintList().get(1).longValue());
+ }
+
+ public void testExtensionUnknownEnumValues() throws Exception {
+ ExtensionRegistry registry = ExtensionRegistry.newInstance();
+ UnittestProto.registerAllExtensions(registry);
+ TestAllExtensions message = TestAllExtensions.parseFrom(payload, registry);
+
+ assertEquals(
+ TestAllTypes.NestedEnum.BAR,
+ message.getExtension(UnittestProto.optionalNestedEnumExtension));
+ assertEquals(2, message.getExtension(UnittestProto.repeatedNestedEnumExtension).size());
+ assertEquals(
+ TestAllTypes.NestedEnum.FOO,
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension, 0));
+ assertEquals(
+ TestAllTypes.NestedEnum.BAZ,
+ message.getExtension(UnittestProto.repeatedNestedEnumExtension, 1));
+
+ // Unknown enum values should be found in UnknownFieldSet.
+ UnknownFieldSet unknown = message.getUnknownFields();
+ assertEquals(
+ 1901, unknown.getField(singularField.getNumber()).getVarintList().get(0).longValue());
+ assertEquals(
+ 1902, unknown.getField(repeatedField.getNumber()).getVarintList().get(0).longValue());
+ assertEquals(
+ 1903, unknown.getField(repeatedField.getNumber()).getVarintList().get(1).longValue());
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java
new file mode 100755
index 000000000..ac9d6df70
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Proto3LiteSchemaTest extends AbstractProto3LiteSchemaTest {
+
+ @Override
+ protected Schema<Proto3MessageLite> schema() {
+ return TestSchemasLite.genericProto3LiteSchema;
+ }
+
+ @Override
+ protected void registerSchemas() {
+ TestSchemasLite.registerGenericProto3LiteSchemas();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java
new file mode 100755
index 000000000..33d5fe0fc
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java
@@ -0,0 +1,450 @@
+// 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.testing.Proto3Testing.Proto3Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Creates instances of {@link Proto3Message} based on the tree configuration. */
+public final class Proto3MessageFactory implements ExperimentalMessageFactory<Proto3Message> {
+ private final int numRepeatedFields;
+ private final int branchingFactor;
+ private final Proto3MessageFactory nextLevel;
+ private final ExperimentalTestDataProvider data;
+
+ public Proto3MessageFactory(
+ int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) {
+ this(
+ new ExperimentalTestDataProvider(stringLength),
+ numRepeatedFields,
+ branchingFactor,
+ treeDepth);
+ }
+
+ private Proto3MessageFactory(
+ ExperimentalTestDataProvider data,
+ int numRepeatedFields,
+ int branchingFactor,
+ int treeDepth) {
+ this.numRepeatedFields = numRepeatedFields;
+ this.branchingFactor = branchingFactor;
+ this.data = data;
+ if (treeDepth > 0) {
+ nextLevel = new Proto3MessageFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1);
+ } else {
+ nextLevel = null;
+ }
+ }
+
+ @Override
+ public ExperimentalTestDataProvider dataProvider() {
+ return data;
+ }
+
+ @Override
+ public Proto3Message newMessage() {
+ Proto3Message.Builder builder = Proto3Message.newBuilder();
+ builder.setFieldDouble1(data.getDouble());
+ builder.setFieldFloat2(data.getFloat());
+ builder.setFieldInt643(data.getLong());
+ builder.setFieldUint644(data.getLong());
+ builder.setFieldInt325(data.getInt());
+ builder.setFieldFixed646(data.getLong());
+ builder.setFieldFixed327(data.getInt());
+ builder.setFieldBool8(data.getBool());
+ builder.setFieldString9(data.getString());
+ // We don't populate the message field. Instead we apply the branching factor to the
+ // repeated message field below.
+ builder.setFieldBytes11(data.getBytes());
+ builder.setFieldUint3212(data.getInt());
+ builder.setFieldEnum13Value(data.getEnum());
+ builder.setFieldSfixed3214(data.getInt());
+ builder.setFieldSfixed6415(data.getLong());
+ builder.setFieldSint3216(data.getInt());
+ builder.setFieldSint6417(data.getLong());
+
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ builder.addFieldDoubleList18(data.getDouble());
+ builder.addFieldFloatList19(data.getFloat());
+ builder.addFieldInt64List20(data.getLong());
+ builder.addFieldUint64List21(data.getLong());
+ builder.addFieldInt32List22(data.getInt());
+ builder.addFieldFixed64List23(data.getLong());
+ builder.addFieldFixed32List24(data.getInt());
+ builder.addFieldBoolList25(data.getBool());
+ builder.addFieldStringList26(data.getString());
+ // Repeated message field is controlled by the branching factor below.
+ builder.addFieldBytesList28(data.getBytes());
+ builder.addFieldUint32List29(data.getInt());
+ builder.addFieldEnumList30Value(data.getEnum());
+ builder.addFieldSfixed32List31(data.getInt());
+ builder.addFieldSfixed64List32(data.getLong());
+ builder.addFieldSint32List33(data.getInt());
+ builder.addFieldSint64List34(data.getLong());
+
+ builder.addFieldDoubleListPacked35(data.getDouble());
+ builder.addFieldFloatListPacked36(data.getFloat());
+ builder.addFieldInt64ListPacked37(data.getLong());
+ builder.addFieldUint64ListPacked38(data.getLong());
+ builder.addFieldInt32ListPacked39(data.getInt());
+ builder.addFieldFixed64ListPacked40(data.getLong());
+ builder.addFieldFixed32ListPacked41(data.getInt());
+ builder.addFieldBoolListPacked42(data.getBool());
+ builder.addFieldUint32ListPacked43(data.getInt());
+ builder.addFieldEnumListPacked44Value(data.getEnum());
+ builder.addFieldSfixed32ListPacked45(data.getInt());
+ builder.addFieldSfixed64ListPacked46(data.getLong());
+ builder.addFieldSint32ListPacked47(data.getInt());
+ builder.addFieldSint64ListPacked48(data.getLong());
+ }
+
+ // Handle the branching factor.
+ if (nextLevel != null) {
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldMessageList27(nextLevel.newMessage());
+ }
+ }
+
+ return builder.build();
+ }
+
+ private interface MapValueProvider<T> {
+ public T getValue();
+ }
+
+ private final MapValueProvider<Integer> integerProvider =
+ new MapValueProvider<Integer>() {
+ @Override
+ public Integer getValue() {
+ return data.getInt();
+ }
+ };
+ private final MapValueProvider<Long> longProvider =
+ new MapValueProvider<Long>() {
+ @Override
+ public Long getValue() {
+ return data.getLong();
+ }
+ };
+ private final MapValueProvider<String> stringProvider =
+ new MapValueProvider<String>() {
+ @Override
+ public String getValue() {
+ return data.getString();
+ }
+ };
+ private final MapValueProvider<ByteString> bytesProvider =
+ new MapValueProvider<ByteString>() {
+ @Override
+ public ByteString getValue() {
+ return data.getBytes();
+ }
+ };
+ private final MapValueProvider<Boolean> booleanProvider =
+ new MapValueProvider<Boolean>() {
+ @Override
+ public Boolean getValue() {
+ return data.getBool();
+ }
+ };
+ private final MapValueProvider<Float> floatProvider =
+ new MapValueProvider<Float>() {
+ @Override
+ public Float getValue() {
+ return data.getFloat();
+ }
+ };
+ private final MapValueProvider<Double> doubleProvider =
+ new MapValueProvider<Double>() {
+ @Override
+ public Double getValue() {
+ return data.getDouble();
+ }
+ };
+ private final MapValueProvider<Proto3Message> messageProvider =
+ new MapValueProvider<Proto3Message>() {
+ @Override
+ public Proto3Message getValue() {
+ return newMessage();
+ }
+ };
+ private final MapValueProvider<Proto3Message.TestEnum> enumProvider =
+ new MapValueProvider<Proto3Message.TestEnum>() {
+ @Override
+ public Proto3Message.TestEnum getValue() {
+ return Proto3Message.TestEnum.forNumber(data.getEnum());
+ }
+ };
+
+ private <V> Map<Integer, V> populateIntegerMap(MapValueProvider<V> provider) {
+ Map<Integer, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getInt(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Long, V> populateLongMap(MapValueProvider<V> provider) {
+ Map<Long, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getLong(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<String, V> populateStringMap(MapValueProvider<V> provider) {
+ Map<String, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getString(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Boolean, V> populateBooleanMap(MapValueProvider<V> provider) {
+ Map<Boolean, V> map = new HashMap<>();
+ map.put(false, provider.getValue());
+ map.put(true, provider.getValue());
+ return map;
+ }
+
+ public Proto3MessageWithMaps newMessageWithMaps() {
+ Proto3MessageWithMaps.Builder builder = Proto3MessageWithMaps.newBuilder();
+
+ builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider));
+ builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider));
+ builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider));
+ builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider));
+ builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider));
+ builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider));
+ builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider));
+ builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider));
+ builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider));
+ builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider));
+ builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider));
+ builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider));
+ builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider));
+ builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider));
+ builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider));
+ builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider));
+ builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider));
+ builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider));
+ builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider));
+ builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider));
+ builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider));
+ builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider));
+ builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64String83(populateLongMap(stringProvider));
+ builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider));
+ builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider));
+ builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider));
+ builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider));
+ builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider));
+ builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider));
+ builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider));
+ builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider));
+ builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64String151(populateLongMap(stringProvider));
+ builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider));
+ builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider));
+ builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider));
+ builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider));
+ builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider));
+ builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider));
+ builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider));
+ builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringInt64162(populateStringMap(longProvider));
+ builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider));
+ builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider));
+ builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSint64167(populateStringMap(longProvider));
+ builder.putAllFieldMapStringString168(populateStringMap(stringProvider));
+ builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringUint64170(populateStringMap(longProvider));
+ builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider));
+ builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider));
+ builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider));
+ builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider));
+ builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider));
+ builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider));
+ builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64String202(populateLongMap(stringProvider));
+ builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider));
+
+ return builder.build();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java
new file mode 100755
index 000000000..364071b35
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageInfoFactory.java
@@ -0,0 +1,506 @@
+// 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.FieldInfo.forField;
+import static com.google.protobuf.FieldInfo.forMapField;
+import static com.google.protobuf.FieldInfo.forOneofMemberField;
+import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
+
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps;
+import com.google.protobuf.testing.Proto3Testing.Proto3Empty;
+import com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps;
+import java.lang.reflect.Field;
+
+/** A factory that generates a hard-coded info for {@link Proto3Message}. */
+public final class Proto3MessageInfoFactory implements MessageInfoFactory {
+ private static final Proto3MessageInfoFactory INSTANCE = new Proto3MessageInfoFactory();
+
+ private Proto3MessageInfoFactory() {}
+
+ public static Proto3MessageInfoFactory getInstance() {
+ return INSTANCE;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ return true;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ if (Proto3Message.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3Message();
+ } else if (Proto3Empty.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3Empty();
+ } else if (Proto3MessageWithMaps.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3MessageWithMaps();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ /**
+ * Creates a new hard-coded info for {@link Proto3Message}. Each time this is called, we manually
+ * go through the entire process of what a message would do if it self-registered its own info,
+ * including looking up each field by name. This is done for benchmarking purposes, so that we get
+ * a more accurate representation of the time it takes to perform this process.
+ */
+ private static StructuralMessageInfo newMessageInfoForProto3Message() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48);
+ lookupFieldsByName(builder);
+ return builder.build();
+ }
+
+ private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) {
+ builder.withDefaultInstance(Proto3Message.getDefaultInstance());
+ builder.withSyntax(ProtoSyntax.PROTO3);
+ builder.withField(forField(field("fieldDouble1_"), 1, FieldType.DOUBLE, true));
+ builder.withField(forField(field("fieldFloat2_"), 2, FieldType.FLOAT, true));
+ builder.withField(forField(field("fieldInt643_"), 3, FieldType.INT64, true));
+ builder.withField(forField(field("fieldUint644_"), 4, FieldType.UINT64, true));
+ builder.withField(forField(field("fieldInt325_"), 5, FieldType.INT32, true));
+ builder.withField(forField(field("fieldFixed646_"), 6, FieldType.FIXED64, true));
+ builder.withField(forField(field("fieldFixed327_"), 7, FieldType.FIXED32, true));
+ builder.withField(forField(field("fieldBool8_"), 8, FieldType.BOOL, true));
+ builder.withField(forField(field("fieldString9_"), 9, FieldType.STRING, true));
+ builder.withField(forField(field("fieldMessage10_"), 10, FieldType.MESSAGE, true));
+ builder.withField(forField(field("fieldBytes11_"), 11, FieldType.BYTES, true));
+ builder.withField(forField(field("fieldUint3212_"), 12, FieldType.UINT32, true));
+ builder.withField(forField(field("fieldEnum13_"), 13, FieldType.ENUM, true));
+ builder.withField(forField(field("fieldSfixed3214_"), 14, FieldType.SFIXED32, true));
+ builder.withField(forField(field("fieldSfixed6415_"), 15, FieldType.SFIXED64, true));
+ builder.withField(forField(field("fieldSint3216_"), 16, FieldType.SINT32, true));
+ builder.withField(forField(field("fieldSint6417_"), 17, FieldType.SINT64, true));
+ builder.withField(forField(field("fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, true));
+ builder.withField(forField(field("fieldFloatList19_"), 19, FieldType.FLOAT_LIST, true));
+ builder.withField(forField(field("fieldInt64List20_"), 20, FieldType.INT64_LIST, true));
+ builder.withField(forField(field("fieldUint64List21_"), 21, FieldType.UINT64_LIST, true));
+ builder.withField(forField(field("fieldInt32List22_"), 22, FieldType.INT32_LIST, true));
+ builder.withField(forField(field("fieldFixed64List23_"), 23, FieldType.FIXED64_LIST, true));
+ builder.withField(forField(field("fieldFixed32List24_"), 24, FieldType.FIXED32_LIST, true));
+ builder.withField(forField(field("fieldBoolList25_"), 25, FieldType.BOOL_LIST, true));
+ builder.withField(forField(field("fieldStringList26_"), 26, FieldType.STRING_LIST, true));
+ builder.withField(
+ forRepeatedMessageField(
+ field("fieldMessageList27_"), 27, FieldType.MESSAGE_LIST, Proto3Message.class));
+ builder.withField(forField(field("fieldBytesList28_"), 28, FieldType.BYTES_LIST, true));
+ builder.withField(forField(field("fieldUint32List29_"), 29, FieldType.UINT32_LIST, true));
+ builder.withField(forField(field("fieldEnumList30_"), 30, FieldType.ENUM_LIST, true));
+ builder.withField(forField(field("fieldSfixed32List31_"), 31, FieldType.SFIXED32_LIST, true));
+ builder.withField(forField(field("fieldSfixed64List32_"), 32, FieldType.SFIXED64_LIST, true));
+ builder.withField(forField(field("fieldSint32List33_"), 33, FieldType.SINT32_LIST, true));
+ builder.withField(forField(field("fieldSint64List34_"), 34, FieldType.SINT64_LIST, true));
+ builder.withField(
+ forField(field("fieldDoubleListPacked35_"), 35, FieldType.DOUBLE_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldFloatListPacked36_"), 36, FieldType.FLOAT_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldInt64ListPacked37_"), 37, FieldType.INT64_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldUint64ListPacked38_"), 38, FieldType.UINT64_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldInt32ListPacked39_"), 39, FieldType.INT32_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldFixed64ListPacked40_"), 40, FieldType.FIXED64_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldFixed32ListPacked41_"), 41, FieldType.FIXED32_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldBoolListPacked42_"), 42, FieldType.BOOL_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldUint32ListPacked43_"), 43, FieldType.UINT32_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldEnumListPacked44_"), 44, FieldType.ENUM_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldSfixed32ListPacked45_"), 45, FieldType.SFIXED32_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldSfixed64ListPacked46_"), 46, FieldType.SFIXED64_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldSint32ListPacked47_"), 47, FieldType.SINT32_LIST_PACKED, true));
+ builder.withField(
+ forField(field("fieldSint64ListPacked48_"), 48, FieldType.SINT64_LIST_PACKED, true));
+
+ OneofInfo oneof = new OneofInfo(0, field("testOneofCase_"), field("testOneof_"));
+ builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, true, null));
+ builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, true, null));
+ builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, true, null));
+ builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, true, null));
+ builder.withField(
+ forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto3Message.class, true, null));
+ builder.withField(
+ forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, true, null));
+ builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, true, null));
+ builder.withField(
+ forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, true, null));
+ }
+
+ private StructuralMessageInfo newMessageInfoForProto3Empty() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO3);
+ return builder.build();
+ }
+
+ private StructuralMessageInfo newMessageInfoForProto3MessageWithMaps() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder();
+ builder.withSyntax(ProtoSyntax.PROTO3);
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_bool_1", 1));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_bytes_2", 2));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_double_3", 3));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_enum_4", 4));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_fixed32_5", 5));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_fixed64_6", 6));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_float_7", 7));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_int32_8", 8));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_int64_9", 9));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_message_10", 10));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sfixed32_11", 11));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sfixed64_12", 12));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sint32_13", 13));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_sint64_14", 14));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_string_15", 15));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_uint32_16", 16));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_bool_uint64_17", 17));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_bool_18", 18));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_bytes_19", 19));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_double_20", 20));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_enum_21", 21));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_fixed32_22", 22));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_fixed64_23", 23));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_float_24", 24));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_int32_25", 25));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_int64_26", 26));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_message_27", 27));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sfixed32_28", 28));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sfixed64_29", 29));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sint32_30", 30));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_sint64_31", 31));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_string_32", 32));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_uint32_33", 33));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed32_uint64_34", 34));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_bool_35", 35));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_bytes_36", 36));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_double_37", 37));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_enum_38", 38));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_fixed32_39", 39));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_fixed64_40", 40));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_float_41", 41));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_int32_42", 42));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_int64_43", 43));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_message_44", 44));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sfixed32_45", 45));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sfixed64_46", 46));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sint32_47", 47));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_sint64_48", 48));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_string_49", 49));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_uint32_50", 50));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_fixed64_uint64_51", 51));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_bool_52", 52));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_bytes_53", 53));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_double_54", 54));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_enum_55", 55));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_fixed32_56", 56));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_fixed64_57", 57));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_float_58", 58));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_int32_59", 59));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_int64_60", 60));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_message_61", 61));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sfixed32_62", 62));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sfixed64_63", 63));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sint32_64", 64));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_sint64_65", 65));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_string_66", 66));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_uint32_67", 67));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int32_uint64_68", 68));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_bool_69", 69));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_bytes_70", 70));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_double_71", 71));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_enum_72", 72));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_fixed32_73", 73));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_fixed64_74", 74));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_float_75", 75));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_int32_76", 76));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_int64_77", 77));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_message_78", 78));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sfixed32_79", 79));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sfixed64_80", 80));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sint32_81", 81));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_sint64_82", 82));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_string_83", 83));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_uint32_84", 84));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_int64_uint64_85", 85));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_bool_86", 86));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_bytes_87", 87));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_double_88", 88));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_enum_89", 89));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_fixed32_90", 90));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_fixed64_91", 91));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_float_92", 92));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_int32_93", 93));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_int64_94", 94));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_message_95", 95));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sfixed32_96", 96));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sfixed64_97", 97));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sint32_98", 98));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_sint64_99", 99));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_string_100", 100));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_uint32_101", 101));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed32_uint64_102", 102));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_bool_103", 103));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_bytes_104", 104));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_double_105", 105));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_enum_106", 106));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_fixed32_107", 107));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_fixed64_108", 108));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_float_109", 109));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_int32_110", 110));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_int64_111", 111));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_message_112", 112));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sfixed32_113", 113));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sfixed64_114", 114));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sint32_115", 115));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_sint64_116", 116));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_string_117", 117));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_uint32_118", 118));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sfixed64_uint64_119", 119));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_bool_120", 120));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_bytes_121", 121));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_double_122", 122));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_enum_123", 123));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_fixed32_124", 124));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_fixed64_125", 125));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_float_126", 126));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_int32_127", 127));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_int64_128", 128));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_message_129", 129));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sfixed32_130", 130));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sfixed64_131", 131));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sint32_132", 132));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_sint64_133", 133));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_string_134", 134));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_uint32_135", 135));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint32_uint64_136", 136));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_bool_137", 137));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_bytes_138", 138));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_double_139", 139));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_enum_140", 140));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_fixed32_141", 141));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_fixed64_142", 142));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_float_143", 143));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_int32_144", 144));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_int64_145", 145));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_message_146", 146));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sfixed32_147", 147));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sfixed64_148", 148));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sint32_149", 149));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_sint64_150", 150));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_string_151", 151));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_uint32_152", 152));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_sint64_uint64_153", 153));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_bool_154", 154));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_bytes_155", 155));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_double_156", 156));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_enum_157", 157));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_fixed32_158", 158));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_fixed64_159", 159));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_float_160", 160));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_int32_161", 161));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_int64_162", 162));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_message_163", 163));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sfixed32_164", 164));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sfixed64_165", 165));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sint32_166", 166));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_sint64_167", 167));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_string_168", 168));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_uint32_169", 169));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_string_uint64_170", 170));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_bool_171", 171));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_bytes_172", 172));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_double_173", 173));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_enum_174", 174));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_fixed32_175", 175));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_fixed64_176", 176));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_float_177", 177));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_int32_178", 178));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_int64_179", 179));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_message_180", 180));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sfixed32_181", 181));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sfixed64_182", 182));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sint32_183", 183));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_sint64_184", 184));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_string_185", 185));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_uint32_186", 186));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint32_uint64_187", 187));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_bool_188", 188));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_bytes_189", 189));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_double_190", 190));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_enum_191", 191));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_fixed32_192", 192));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_fixed64_193", 193));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_float_194", 194));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_int32_195", 195));
+ builder.withField(mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_int64_196", 196));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_message_197", 197));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sfixed32_198", 198));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sfixed64_199", 199));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sint32_200", 200));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_sint64_201", 201));
+ builder.withField(
+ mapFieldInfo(Proto3MessageWithMaps.class, "field_map_uint64_string_202", 202));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint32_203", 203));
+ builder.withField(
+ mapFieldInfo(Proto2MessageWithMaps.class, "field_map_uint64_uint64_204", 204));
+ return builder.build();
+ }
+
+ private static Field field(String name) {
+ return field(Proto3Message.class, name);
+ }
+
+ private static Field field(Class<?> clazz, String name) {
+ try {
+ return clazz.getDeclaredField(name);
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static FieldInfo mapFieldInfo(Class<?> clazz, String fieldName, int fieldNumber) {
+ try {
+ return forMapField(
+ field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"),
+ fieldNumber,
+ SchemaUtil.getMapDefaultEntry(clazz, fieldName),
+ null);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java
new file mode 100755
index 000000000..2f6947da4
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java
@@ -0,0 +1,452 @@
+// 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.testing.Proto3TestingLite.Proto3MessageLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Creates instances of {@link Proto3MessageLite} based on the tree configuration. */
+public final class Proto3MessageLiteFactory
+ implements ExperimentalMessageFactory<Proto3MessageLite> {
+ private final int numRepeatedFields;
+ private final int branchingFactor;
+ private final Proto3MessageLiteFactory nextLevel;
+ private final ExperimentalTestDataProvider data;
+
+ public Proto3MessageLiteFactory(
+ int numRepeatedFields, int stringLength, int branchingFactor, int treeDepth) {
+ this(
+ new ExperimentalTestDataProvider(stringLength),
+ numRepeatedFields,
+ branchingFactor,
+ treeDepth);
+ }
+
+ private Proto3MessageLiteFactory(
+ ExperimentalTestDataProvider data,
+ int numRepeatedFields,
+ int branchingFactor,
+ int treeDepth) {
+ this.numRepeatedFields = numRepeatedFields;
+ this.branchingFactor = branchingFactor;
+ this.data = data;
+ if (treeDepth > 0) {
+ nextLevel =
+ new Proto3MessageLiteFactory(data, numRepeatedFields, branchingFactor, treeDepth - 1);
+ } else {
+ nextLevel = null;
+ }
+ }
+
+ @Override
+ public ExperimentalTestDataProvider dataProvider() {
+ return data;
+ }
+
+ @Override
+ public Proto3MessageLite newMessage() {
+ Proto3MessageLite.Builder builder = Proto3MessageLite.newBuilder();
+ builder.setFieldDouble1(data.getDouble());
+ builder.setFieldFloat2(data.getFloat());
+ builder.setFieldInt643(data.getLong());
+ builder.setFieldUint644(data.getLong());
+ builder.setFieldInt325(data.getInt());
+ builder.setFieldFixed646(data.getLong());
+ builder.setFieldFixed327(data.getInt());
+ builder.setFieldBool8(data.getBool());
+ builder.setFieldString9(data.getString());
+ // We don't populate the message field. Instead we apply the branching factor to the
+ // repeated message field below.
+ builder.setFieldBytes11(data.getBytes());
+ builder.setFieldUint3212(data.getInt());
+ builder.setFieldEnum13Value(data.getEnum());
+ builder.setFieldSfixed3214(data.getInt());
+ builder.setFieldSfixed6415(data.getLong());
+ builder.setFieldSint3216(data.getInt());
+ builder.setFieldSint6417(data.getLong());
+
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ builder.addFieldDoubleList18(data.getDouble());
+ builder.addFieldFloatList19(data.getFloat());
+ builder.addFieldInt64List20(data.getLong());
+ builder.addFieldUint64List21(data.getLong());
+ builder.addFieldInt32List22(data.getInt());
+ builder.addFieldFixed64List23(data.getLong());
+ builder.addFieldFixed32List24(data.getInt());
+ builder.addFieldBoolList25(data.getBool());
+ builder.addFieldStringList26(data.getString());
+ // Repeated message field is controlled by the branching factor below.
+ builder.addFieldBytesList28(data.getBytes());
+ builder.addFieldUint32List29(data.getInt());
+ builder.addFieldEnumList30Value(data.getEnum());
+ builder.addFieldSfixed32List31(data.getInt());
+ builder.addFieldSfixed64List32(data.getLong());
+ builder.addFieldSint32List33(data.getInt());
+ builder.addFieldSint64List34(data.getLong());
+
+ builder.addFieldDoubleListPacked35(data.getDouble());
+ builder.addFieldFloatListPacked36(data.getFloat());
+ builder.addFieldInt64ListPacked37(data.getLong());
+ builder.addFieldUint64ListPacked38(data.getLong());
+ builder.addFieldInt32ListPacked39(data.getInt());
+ builder.addFieldFixed64ListPacked40(data.getLong());
+ builder.addFieldFixed32ListPacked41(data.getInt());
+ builder.addFieldBoolListPacked42(data.getBool());
+ builder.addFieldUint32ListPacked43(data.getInt());
+ builder.addFieldEnumListPacked44Value(data.getEnum());
+ builder.addFieldSfixed32ListPacked45(data.getInt());
+ builder.addFieldSfixed64ListPacked46(data.getLong());
+ builder.addFieldSint32ListPacked47(data.getInt());
+ builder.addFieldSint64ListPacked48(data.getLong());
+ }
+
+ // Handle the branching factor.
+ if (nextLevel != null) {
+ for (int i = 0; i < branchingFactor; ++i) {
+ builder.addFieldMessageList27(nextLevel.newMessage());
+ }
+ }
+
+ return builder.build();
+ }
+
+ private interface MapValueProvider<T> {
+ public T getValue();
+ }
+
+ private final MapValueProvider<Integer> integerProvider =
+ new MapValueProvider<Integer>() {
+ @Override
+ public Integer getValue() {
+ return data.getInt();
+ }
+ };
+ private final MapValueProvider<Long> longProvider =
+ new MapValueProvider<Long>() {
+ @Override
+ public Long getValue() {
+ return data.getLong();
+ }
+ };
+ private final MapValueProvider<String> stringProvider =
+ new MapValueProvider<String>() {
+ @Override
+ public String getValue() {
+ return data.getString();
+ }
+ };
+ private final MapValueProvider<ByteString> bytesProvider =
+ new MapValueProvider<ByteString>() {
+ @Override
+ public ByteString getValue() {
+ return data.getBytes();
+ }
+ };
+ private final MapValueProvider<Boolean> booleanProvider =
+ new MapValueProvider<Boolean>() {
+ @Override
+ public Boolean getValue() {
+ return data.getBool();
+ }
+ };
+ private final MapValueProvider<Float> floatProvider =
+ new MapValueProvider<Float>() {
+ @Override
+ public Float getValue() {
+ return data.getFloat();
+ }
+ };
+ private final MapValueProvider<Double> doubleProvider =
+ new MapValueProvider<Double>() {
+ @Override
+ public Double getValue() {
+ return data.getDouble();
+ }
+ };
+ private final MapValueProvider<Proto3MessageLite> messageProvider =
+ new MapValueProvider<Proto3MessageLite>() {
+ @Override
+ public Proto3MessageLite getValue() {
+ return newMessage();
+ }
+ };
+ private final MapValueProvider<Proto3MessageLite.TestEnum> enumProvider =
+ new MapValueProvider<Proto3MessageLite.TestEnum>() {
+ @Override
+ public Proto3MessageLite.TestEnum getValue() {
+ return Proto3MessageLite.TestEnum.forNumber(data.getEnum());
+ }
+ };
+
+ private <V> Map<Integer, V> populateIntegerMap(MapValueProvider<V> provider) {
+ Map<Integer, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getInt(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Long, V> populateLongMap(MapValueProvider<V> provider) {
+ Map<Long, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getLong(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<String, V> populateStringMap(MapValueProvider<V> provider) {
+ Map<String, V> map = new HashMap<>();
+ for (int i = 0; i < numRepeatedFields; ++i) {
+ map.put(data.getString(), provider.getValue());
+ }
+ return map;
+ }
+
+ private <V> Map<Boolean, V> populateBooleanMap(MapValueProvider<V> provider) {
+ Map<Boolean, V> map = new HashMap<>();
+ map.put(false, provider.getValue());
+ map.put(true, provider.getValue());
+ return map;
+ }
+
+ public Proto3MessageLiteWithMaps newMessageWithMaps() {
+ Proto3MessageLiteWithMaps.Builder builder = Proto3MessageLiteWithMaps.newBuilder();
+
+ builder.putAllFieldMapBoolBool1(populateBooleanMap(booleanProvider));
+ builder.putAllFieldMapBoolBytes2(populateBooleanMap(bytesProvider));
+ builder.putAllFieldMapBoolDouble3(populateBooleanMap(doubleProvider));
+ builder.putAllFieldMapBoolEnum4(populateBooleanMap(enumProvider));
+ builder.putAllFieldMapBoolFixed325(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolFixed646(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolFloat7(populateBooleanMap(floatProvider));
+ builder.putAllFieldMapBoolInt328(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolInt649(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolMessage10(populateBooleanMap(messageProvider));
+ builder.putAllFieldMapBoolSfixed3211(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSfixed6412(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolSint3213(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolSint6414(populateBooleanMap(longProvider));
+ builder.putAllFieldMapBoolString15(populateBooleanMap(stringProvider));
+ builder.putAllFieldMapBoolUint3216(populateBooleanMap(integerProvider));
+ builder.putAllFieldMapBoolUint6417(populateBooleanMap(longProvider));
+ builder.putAllFieldMapFixed32Bool18(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapFixed32Bytes19(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapFixed32Double20(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapFixed32Enum21(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapFixed32Fixed3222(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Fixed6423(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Float24(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapFixed32Int3225(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Int6426(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Message27(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapFixed32Sfixed3228(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sfixed6429(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32Sint3230(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Sint6431(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed32String32(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapFixed32Uint3233(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapFixed32Uint6434(populateIntegerMap(longProvider));
+ builder.putAllFieldMapFixed64Bool35(populateLongMap(booleanProvider));
+ builder.putAllFieldMapFixed64Bytes36(populateLongMap(bytesProvider));
+ builder.putAllFieldMapFixed64Double37(populateLongMap(doubleProvider));
+ builder.putAllFieldMapFixed64Enum38(populateLongMap(enumProvider));
+ builder.putAllFieldMapFixed64Fixed3239(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Fixed6440(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Float41(populateLongMap(floatProvider));
+ builder.putAllFieldMapFixed64Int3242(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Int6443(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Message44(populateLongMap(messageProvider));
+ builder.putAllFieldMapFixed64Sfixed3245(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sfixed6446(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64Sint3247(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Sint6448(populateLongMap(longProvider));
+ builder.putAllFieldMapFixed64String49(populateLongMap(stringProvider));
+ builder.putAllFieldMapFixed64Uint3250(populateLongMap(integerProvider));
+ builder.putAllFieldMapFixed64Uint6451(populateLongMap(longProvider));
+ builder.putAllFieldMapInt32Bool52(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapInt32Bytes53(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapInt32Double54(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapInt32Enum55(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapInt32Fixed3256(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Fixed6457(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Float58(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapInt32Int3259(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Int6460(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Message61(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapInt32Sfixed3262(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sfixed6463(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32Sint3264(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Sint6465(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt32String66(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapInt32Uint3267(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapInt32Uint6468(populateIntegerMap(longProvider));
+ builder.putAllFieldMapInt64Bool69(populateLongMap(booleanProvider));
+ builder.putAllFieldMapInt64Bytes70(populateLongMap(bytesProvider));
+ builder.putAllFieldMapInt64Double71(populateLongMap(doubleProvider));
+ builder.putAllFieldMapInt64Enum72(populateLongMap(enumProvider));
+ builder.putAllFieldMapInt64Fixed3273(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Fixed6474(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Float75(populateLongMap(floatProvider));
+ builder.putAllFieldMapInt64Int3276(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Int6477(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Message78(populateLongMap(messageProvider));
+ builder.putAllFieldMapInt64Sfixed3279(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sfixed6480(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64Sint3281(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Sint6482(populateLongMap(longProvider));
+ builder.putAllFieldMapInt64String83(populateLongMap(stringProvider));
+ builder.putAllFieldMapInt64Uint3284(populateLongMap(integerProvider));
+ builder.putAllFieldMapInt64Uint6485(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed32Bool86(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSfixed32Bytes87(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSfixed32Double88(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSfixed32Enum89(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSfixed32Fixed3290(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Fixed6491(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Float92(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSfixed32Int3293(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Int6494(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Message95(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSfixed32Sfixed3296(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sfixed6497(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32Sint3298(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Sint6499(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed32String100(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSfixed32Uint32101(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSfixed32Uint64102(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSfixed64Bool103(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSfixed64Bytes104(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSfixed64Double105(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSfixed64Enum106(populateLongMap(enumProvider));
+ builder.putAllFieldMapSfixed64Fixed32107(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Fixed64108(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Float109(populateLongMap(floatProvider));
+ builder.putAllFieldMapSfixed64Int32110(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Int64111(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Message112(populateLongMap(messageProvider));
+ builder.putAllFieldMapSfixed64Sfixed32113(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sfixed64114(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64Sint32115(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Sint64116(populateLongMap(longProvider));
+ builder.putAllFieldMapSfixed64String117(populateLongMap(stringProvider));
+ builder.putAllFieldMapSfixed64Uint32118(populateLongMap(integerProvider));
+ builder.putAllFieldMapSfixed64Uint64119(populateLongMap(longProvider));
+ builder.putAllFieldMapSint32Bool120(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapSint32Bytes121(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapSint32Double122(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapSint32Enum123(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapSint32Fixed32124(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Fixed64125(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Float126(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapSint32Int32127(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Int64128(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Message129(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapSint32Sfixed32130(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sfixed64131(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32Sint32132(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Sint64133(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint32String134(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapSint32Uint32135(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapSint32Uint64136(populateIntegerMap(longProvider));
+ builder.putAllFieldMapSint64Bool137(populateLongMap(booleanProvider));
+ builder.putAllFieldMapSint64Bytes138(populateLongMap(bytesProvider));
+ builder.putAllFieldMapSint64Double139(populateLongMap(doubleProvider));
+ builder.putAllFieldMapSint64Enum140(populateLongMap(enumProvider));
+ builder.putAllFieldMapSint64Fixed32141(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Fixed64142(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Float143(populateLongMap(floatProvider));
+ builder.putAllFieldMapSint64Int32144(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Int64145(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Message146(populateLongMap(messageProvider));
+ builder.putAllFieldMapSint64Sfixed32147(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sfixed64148(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64Sint32149(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Sint64150(populateLongMap(longProvider));
+ builder.putAllFieldMapSint64String151(populateLongMap(stringProvider));
+ builder.putAllFieldMapSint64Uint32152(populateLongMap(integerProvider));
+ builder.putAllFieldMapSint64Uint64153(populateLongMap(longProvider));
+ builder.putAllFieldMapStringBool154(populateStringMap(booleanProvider));
+ builder.putAllFieldMapStringBytes155(populateStringMap(bytesProvider));
+ builder.putAllFieldMapStringDouble156(populateStringMap(doubleProvider));
+ builder.putAllFieldMapStringEnum157(populateStringMap(enumProvider));
+ builder.putAllFieldMapStringFixed32158(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringFixed64159(populateStringMap(longProvider));
+ builder.putAllFieldMapStringFloat160(populateStringMap(floatProvider));
+ builder.putAllFieldMapStringInt32161(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringInt64162(populateStringMap(longProvider));
+ builder.putAllFieldMapStringMessage163(populateStringMap(messageProvider));
+ builder.putAllFieldMapStringSfixed32164(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSfixed64165(populateStringMap(longProvider));
+ builder.putAllFieldMapStringSint32166(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringSint64167(populateStringMap(longProvider));
+ builder.putAllFieldMapStringString168(populateStringMap(stringProvider));
+ builder.putAllFieldMapStringUint32169(populateStringMap(integerProvider));
+ builder.putAllFieldMapStringUint64170(populateStringMap(longProvider));
+ builder.putAllFieldMapUint32Bool171(populateIntegerMap(booleanProvider));
+ builder.putAllFieldMapUint32Bytes172(populateIntegerMap(bytesProvider));
+ builder.putAllFieldMapUint32Double173(populateIntegerMap(doubleProvider));
+ builder.putAllFieldMapUint32Enum174(populateIntegerMap(enumProvider));
+ builder.putAllFieldMapUint32Fixed32175(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Fixed64176(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Float177(populateIntegerMap(floatProvider));
+ builder.putAllFieldMapUint32Int32178(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Int64179(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Message180(populateIntegerMap(messageProvider));
+ builder.putAllFieldMapUint32Sfixed32181(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sfixed64182(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32Sint32183(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Sint64184(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint32String185(populateIntegerMap(stringProvider));
+ builder.putAllFieldMapUint32Uint32186(populateIntegerMap(integerProvider));
+ builder.putAllFieldMapUint32Uint64187(populateIntegerMap(longProvider));
+ builder.putAllFieldMapUint64Bool188(populateLongMap(booleanProvider));
+ builder.putAllFieldMapUint64Bytes189(populateLongMap(bytesProvider));
+ builder.putAllFieldMapUint64Double190(populateLongMap(doubleProvider));
+ builder.putAllFieldMapUint64Enum191(populateLongMap(enumProvider));
+ builder.putAllFieldMapUint64Fixed32192(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Fixed64193(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Float194(populateLongMap(floatProvider));
+ builder.putAllFieldMapUint64Int32195(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Int64196(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Message197(populateLongMap(messageProvider));
+ builder.putAllFieldMapUint64Sfixed32198(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sfixed64199(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64Sint32200(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Sint64201(populateLongMap(longProvider));
+ builder.putAllFieldMapUint64String202(populateLongMap(stringProvider));
+ builder.putAllFieldMapUint64Uint32203(populateLongMap(integerProvider));
+ builder.putAllFieldMapUint64Uint64204(populateLongMap(longProvider));
+
+ return builder.build();
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
new file mode 100755
index 000000000..66e406af7
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3MessageLiteInfoFactory.java
@@ -0,0 +1,816 @@
+// 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.FieldInfo.forField;
+import static com.google.protobuf.FieldInfo.forMapField;
+import static com.google.protobuf.FieldInfo.forOneofMemberField;
+import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
+
+import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps;
+import java.lang.reflect.Field;
+
+/** A factory that generates a hard-coded info for {@link Proto3MessageLite}. */
+public final class Proto3MessageLiteInfoFactory implements MessageInfoFactory {
+ private static final Proto3MessageLiteInfoFactory instanceForRawMessageInfo =
+ new Proto3MessageLiteInfoFactory(true);
+ private static final Proto3MessageLiteInfoFactory instanceForStructuralMessageInfo =
+ new Proto3MessageLiteInfoFactory(false);
+
+ public static Proto3MessageLiteInfoFactory getInstanceForRawMessageInfo() {
+ return instanceForRawMessageInfo;
+ }
+
+ public static Proto3MessageLiteInfoFactory getInstanceForStructuralMessageInfo() {
+ return instanceForStructuralMessageInfo;
+ }
+
+ private final boolean produceRawMessageInfo;
+
+ private Proto3MessageLiteInfoFactory(boolean produceRawMessageInfo) {
+ this.produceRawMessageInfo = produceRawMessageInfo;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ return true;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ return produceRawMessageInfo ? rawMessageInfoFor(clazz) : structuralMessageInfoFor(clazz);
+ }
+
+ private MessageInfo rawMessageInfoFor(Class<?> clazz) {
+ if (Proto3MessageLite.class.isAssignableFrom(clazz)) {
+ return newRawMessageInfoForProto3MessageLite();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ private MessageInfo newRawMessageInfoForProto3MessageLite() {
+ java.lang.Object[] objects =
+ new java.lang.Object[] {
+ "testOneof_",
+ "testOneofCase_",
+ "fieldDouble1_",
+ "fieldFloat2_",
+ "fieldInt643_",
+ "fieldUint644_",
+ "fieldInt325_",
+ "fieldFixed646_",
+ "fieldFixed327_",
+ "fieldBool8_",
+ "fieldString9_",
+ "fieldMessage10_",
+ "fieldBytes11_",
+ "fieldUint3212_",
+ "fieldEnum13_",
+ "fieldSfixed3214_",
+ "fieldSfixed6415_",
+ "fieldSint3216_",
+ "fieldSint6417_",
+ "fieldDoubleList18_",
+ "fieldFloatList19_",
+ "fieldInt64List20_",
+ "fieldUint64List21_",
+ "fieldInt32List22_",
+ "fieldFixed64List23_",
+ "fieldFixed32List24_",
+ "fieldBoolList25_",
+ "fieldStringList26_",
+ "fieldMessageList27_",
+ Proto3MessageLite.class,
+ "fieldBytesList28_",
+ "fieldUint32List29_",
+ "fieldEnumList30_",
+ "fieldSfixed32List31_",
+ "fieldSfixed64List32_",
+ "fieldSint32List33_",
+ "fieldSint64List34_",
+ "fieldDoubleListPacked35_",
+ "fieldFloatListPacked36_",
+ "fieldInt64ListPacked37_",
+ "fieldUint64ListPacked38_",
+ "fieldInt32ListPacked39_",
+ "fieldFixed64ListPacked40_",
+ "fieldFixed32ListPacked41_",
+ "fieldBoolListPacked42_",
+ "fieldUint32ListPacked43_",
+ "fieldEnumListPacked44_",
+ "fieldSfixed32ListPacked45_",
+ "fieldSfixed64ListPacked46_",
+ "fieldSint32ListPacked47_",
+ "fieldSint64ListPacked48_",
+ Proto3MessageLite.class,
+ };
+ // To update this after a proto change, run protoc on proto3_message_lite.proto and copy over
+ // the content of the generated buildMessageInfo() method here.
+ java.lang.String info =
+ "\u0000@\u0001\u0000\u0001D@\u0000\u001f\u0000\u0001\u0000\u0002\u0001\u0003\u0002"
+ + "\u0004\u0003\u0005\u0004\u0006\u0005\u0007\u0006\b\u0007\t\u0208\n\t\u000b\n\f\u000b"
+ + "\r\f\u000e\r\u000f\u000e\u0010\u000f\u0011\u0010\u0012\u0012\u0013\u0013\u0014\u0014"
+ + "\u0015\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u021a\u001b\u001b"
+ + "\u001c\u001c\u001d\u001d\u001e\u001e\u001f\u001f !!\"\"##$$%%&&\'\'(())**++,,--"
+ + "..//0053\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000=\u023b\u0000"
+ + "><\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000";
+ return new RawMessageInfo(Proto3MessageLite.getDefaultInstance(), info, objects);
+ }
+
+ private MessageInfo structuralMessageInfoFor(Class<?> clazz) {
+ if (Proto3MessageLite.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3MessageLite();
+ } else if (Proto3EmptyLite.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3EmptyLite();
+ } else if (Proto3MessageLiteWithMaps.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto3MessageLiteWithMaps();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ /**
+ * Creates a new hard-coded info for {@link Proto3MessageLite}. Each time this is called, we
+ * manually go through the entire process of what a message would do if it self-registered its own
+ * info, including looking up each field by name. This is done for benchmarking purposes, so that
+ * we get a more accurate representation of the time it takes to perform this process.
+ */
+ private static StructuralMessageInfo newMessageInfoForProto3MessageLite() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48);
+ lookupFieldsByName(builder);
+ return builder.build();
+ }
+
+ private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) {
+ builder.withDefaultInstance(Proto3MessageLite.getDefaultInstance());
+ builder.withSyntax(ProtoSyntax.PROTO3);
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldDouble1_"), 1, FieldType.DOUBLE, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldFloat2_"), 2, FieldType.FLOAT, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldInt643_"), 3, FieldType.INT64, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldUint644_"), 4, FieldType.UINT64, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldInt325_"), 5, FieldType.INT32, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldFixed646_"), 6, FieldType.FIXED64, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldFixed327_"), 7, FieldType.FIXED32, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldBool8_"), 8, FieldType.BOOL, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldString9_"), 9, FieldType.STRING, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldMessage10_"), 10, FieldType.MESSAGE, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldBytes11_"), 11, FieldType.BYTES, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldUint3212_"), 12, FieldType.UINT32, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldEnum13_"), 13, FieldType.ENUM, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldSfixed3214_"), 14, FieldType.SFIXED32, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldSfixed6415_"), 15, FieldType.SFIXED64, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldSint3216_"), 16, FieldType.SINT32, true));
+ builder.withField(
+ forField(field(Proto3MessageLite.class, "fieldSint6417_"), 17, FieldType.SINT64, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldDoubleList18_"), 18, FieldType.DOUBLE_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFloatList19_"), 19, FieldType.FLOAT_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldInt64List20_"), 20, FieldType.INT64_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldUint64List21_"), 21, FieldType.UINT64_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldInt32List22_"), 22, FieldType.INT32_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFixed64List23_"),
+ 23,
+ FieldType.FIXED64_LIST,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFixed32List24_"),
+ 24,
+ FieldType.FIXED32_LIST,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldBoolList25_"), 25, FieldType.BOOL_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldStringList26_"), 26, FieldType.STRING_LIST, true));
+ builder.withField(
+ forRepeatedMessageField(
+ field(Proto3MessageLite.class, "fieldMessageList27_"),
+ 27,
+ FieldType.MESSAGE_LIST,
+ Proto3MessageLite.class));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldBytesList28_"), 28, FieldType.BYTES_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldUint32List29_"), 29, FieldType.UINT32_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldEnumList30_"), 30, FieldType.ENUM_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSfixed32List31_"),
+ 31,
+ FieldType.SFIXED32_LIST,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSfixed64List32_"),
+ 32,
+ FieldType.SFIXED64_LIST,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSint32List33_"), 33, FieldType.SINT32_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSint64List34_"), 34, FieldType.SINT64_LIST, true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldDoubleListPacked35_"),
+ 35,
+ FieldType.DOUBLE_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFloatListPacked36_"),
+ 36,
+ FieldType.FLOAT_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldInt64ListPacked37_"),
+ 37,
+ FieldType.INT64_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldUint64ListPacked38_"),
+ 38,
+ FieldType.UINT64_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldInt32ListPacked39_"),
+ 39,
+ FieldType.INT32_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFixed64ListPacked40_"),
+ 40,
+ FieldType.FIXED64_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldFixed32ListPacked41_"),
+ 41,
+ FieldType.FIXED32_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldBoolListPacked42_"),
+ 42,
+ FieldType.BOOL_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldUint32ListPacked43_"),
+ 43,
+ FieldType.UINT32_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldEnumListPacked44_"),
+ 44,
+ FieldType.ENUM_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSfixed32ListPacked45_"),
+ 45,
+ FieldType.SFIXED32_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSfixed64ListPacked46_"),
+ 46,
+ FieldType.SFIXED64_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSint32ListPacked47_"),
+ 47,
+ FieldType.SINT32_LIST_PACKED,
+ true));
+ builder.withField(
+ forField(
+ field(Proto3MessageLite.class, "fieldSint64ListPacked48_"),
+ 48,
+ FieldType.SINT64_LIST_PACKED,
+ true));
+
+ OneofInfo oneof =
+ new OneofInfo(
+ 0,
+ field(Proto3MessageLite.class, "testOneofCase_"),
+ field(Proto3MessageLite.class, "testOneof_"));
+ builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, true, null));
+ builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, true, null));
+ builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, true, null));
+ builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, true, null));
+ builder.withField(
+ forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto3MessageLite.class, true, null));
+ builder.withField(
+ forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, true, null));
+ builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, true, null));
+ builder.withField(
+ forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, true, null));
+ builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, true, null));
+ builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, true, null));
+ }
+
+ private StructuralMessageInfo newMessageInfoForProto3EmptyLite() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO3);
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto3MessageLiteWithMaps() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder();
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_bool_1", 1));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_bytes_2", 2));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_double_3", 3));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_enum_4", 4));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_fixed32_5", 5));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_fixed64_6", 6));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_float_7", 7));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_int32_8", 8));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_int64_9", 9));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_message_10", 10));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sfixed32_11", 11));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sfixed64_12", 12));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sint32_13", 13));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_sint64_14", 14));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_string_15", 15));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_uint32_16", 16));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_bool_uint64_17", 17));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_bool_18", 18));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_bytes_19", 19));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_double_20", 20));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_enum_21", 21));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_fixed32_22", 22));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_fixed64_23", 23));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_float_24", 24));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_int32_25", 25));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_int64_26", 26));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_message_27", 27));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sfixed32_28", 28));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sfixed64_29", 29));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sint32_30", 30));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_sint64_31", 31));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_string_32", 32));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_uint32_33", 33));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed32_uint64_34", 34));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_bool_35", 35));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_bytes_36", 36));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_double_37", 37));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_enum_38", 38));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_fixed32_39", 39));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_fixed64_40", 40));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_float_41", 41));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_int32_42", 42));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_int64_43", 43));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_message_44", 44));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sfixed32_45", 45));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sfixed64_46", 46));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sint32_47", 47));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_sint64_48", 48));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_string_49", 49));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_uint32_50", 50));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_fixed64_uint64_51", 51));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_bool_52", 52));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_bytes_53", 53));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_double_54", 54));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_enum_55", 55));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_fixed32_56", 56));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_fixed64_57", 57));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_float_58", 58));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_int32_59", 59));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_int64_60", 60));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_message_61", 61));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sfixed32_62", 62));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sfixed64_63", 63));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sint32_64", 64));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_sint64_65", 65));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_string_66", 66));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_uint32_67", 67));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int32_uint64_68", 68));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_bool_69", 69));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_bytes_70", 70));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_double_71", 71));
+ builder.withField(mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_enum_72", 72));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_fixed32_73", 73));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_fixed64_74", 74));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_float_75", 75));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_int32_76", 76));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_int64_77", 77));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_message_78", 78));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sfixed32_79", 79));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sfixed64_80", 80));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sint32_81", 81));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_sint64_82", 82));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_string_83", 83));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_uint32_84", 84));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_int64_uint64_85", 85));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_bool_86", 86));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_bytes_87", 87));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_double_88", 88));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_enum_89", 89));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_fixed32_90", 90));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_fixed64_91", 91));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_float_92", 92));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_int32_93", 93));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_int64_94", 94));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_message_95", 95));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sfixed32_96", 96));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sfixed64_97", 97));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sint32_98", 98));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_sint64_99", 99));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_string_100", 100));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_uint32_101", 101));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed32_uint64_102", 102));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_bool_103", 103));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_bytes_104", 104));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_double_105", 105));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_enum_106", 106));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_fixed32_107", 107));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_fixed64_108", 108));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_float_109", 109));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_int32_110", 110));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_int64_111", 111));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_message_112", 112));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sfixed32_113", 113));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sfixed64_114", 114));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sint32_115", 115));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_sint64_116", 116));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_string_117", 117));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_uint32_118", 118));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sfixed64_uint64_119", 119));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_bool_120", 120));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_bytes_121", 121));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_double_122", 122));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_enum_123", 123));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_fixed32_124", 124));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_fixed64_125", 125));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_float_126", 126));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_int32_127", 127));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_int64_128", 128));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_message_129", 129));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sfixed32_130", 130));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sfixed64_131", 131));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sint32_132", 132));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_sint64_133", 133));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_string_134", 134));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_uint32_135", 135));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint32_uint64_136", 136));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_bool_137", 137));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_bytes_138", 138));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_double_139", 139));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_enum_140", 140));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_fixed32_141", 141));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_fixed64_142", 142));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_float_143", 143));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_int32_144", 144));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_int64_145", 145));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_message_146", 146));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sfixed32_147", 147));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sfixed64_148", 148));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sint32_149", 149));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_sint64_150", 150));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_string_151", 151));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_uint32_152", 152));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_sint64_uint64_153", 153));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_bool_154", 154));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_bytes_155", 155));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_double_156", 156));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_enum_157", 157));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_fixed32_158", 158));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_fixed64_159", 159));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_float_160", 160));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_int32_161", 161));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_int64_162", 162));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_message_163", 163));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sfixed32_164", 164));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sfixed64_165", 165));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sint32_166", 166));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_sint64_167", 167));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_string_168", 168));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_uint32_169", 169));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_string_uint64_170", 170));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_bool_171", 171));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_bytes_172", 172));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_double_173", 173));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_enum_174", 174));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_fixed32_175", 175));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_fixed64_176", 176));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_float_177", 177));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_int32_178", 178));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_int64_179", 179));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_message_180", 180));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sfixed32_181", 181));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sfixed64_182", 182));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sint32_183", 183));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_sint64_184", 184));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_string_185", 185));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_uint32_186", 186));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint32_uint64_187", 187));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_bool_188", 188));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_bytes_189", 189));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_double_190", 190));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_enum_191", 191));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_fixed32_192", 192));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_fixed64_193", 193));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_float_194", 194));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_int32_195", 195));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_int64_196", 196));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_message_197", 197));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sfixed32_198", 198));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sfixed64_199", 199));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sint32_200", 200));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_sint64_201", 201));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_string_202", 202));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_uint32_203", 203));
+ builder.withField(
+ mapFieldInfo(Proto3MessageLiteWithMaps.class, "field_map_uint64_uint64_204", 204));
+
+ return builder.build();
+ }
+
+ private static Field field(Class<?> clazz, String name) {
+ try {
+ return clazz.getDeclaredField(name);
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static FieldInfo mapFieldInfo(Class<?> clazz, String fieldName, int fieldNumber) {
+ try {
+ return forMapField(
+ field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"),
+ fieldNumber,
+ SchemaUtil.getMapDefaultEntry(clazz, fieldName),
+ null);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java b/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java
new file mode 100755
index 000000000..5cd145be7
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.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 com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class Proto3SchemaTest extends AbstractProto3SchemaTest {
+ @Override
+ protected void registerSchemas() {
+ TestSchemas.registerGenericProto3Schemas();
+ }
+
+ @Override
+ protected Schema<Proto3Message> schema() {
+ return TestSchemas.genericProto3Schema;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TestSchemas.java b/java/core/src/test/java/com/google/protobuf/TestSchemas.java
new file mode 100755
index 000000000..ab0ced4cd
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TestSchemas.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.testing.Proto2Testing;
+import com.google.protobuf.testing.Proto2Testing.Proto2Empty;
+import com.google.protobuf.testing.Proto2Testing.Proto2Message;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithExtensions;
+import com.google.protobuf.testing.Proto2Testing.Proto2MessageWithMaps;
+import com.google.protobuf.testing.Proto3Testing.Proto3Empty;
+import com.google.protobuf.testing.Proto3Testing.Proto3Message;
+import com.google.protobuf.testing.Proto3Testing.Proto3MessageWithMaps;
+
+/** Schemas to support testing. */
+public class TestSchemas {
+ public static final Schema<Proto2Message> genericProto2Schema =
+ new ManifestSchemaFactory().createSchema(Proto2Message.class);
+ public static final Schema<Proto3Message> genericProto3Schema =
+ new ManifestSchemaFactory().createSchema(Proto3Message.class);
+
+ public static void registerGenericProto2Schemas() {
+ registerProto2Schemas();
+ }
+
+ public static void registerGenericProto3Schemas() {
+ registerProto3Schemas();
+ }
+
+ private static void registerProto2Schemas() {
+ Protobuf protobuf = Protobuf.getInstance();
+ ManifestSchemaFactory factory = new ManifestSchemaFactory();
+ protobuf.registerSchemaOverride(Proto2Message.class, factory.createSchema(Proto2Message.class));
+ protobuf.registerSchemaOverride(
+ Proto2Message.FieldGroup49.class, factory.createSchema(Proto2Message.FieldGroup49.class));
+ protobuf.registerSchemaOverride(
+ Proto2Message.FieldGroupList51.class,
+ factory.createSchema(Proto2Message.FieldGroupList51.class));
+ protobuf.registerSchemaOverride(
+ Proto2Message.FieldGroup69.class, factory.createSchema(Proto2Message.FieldGroup69.class));
+ protobuf.registerSchemaOverride(
+ Proto2Message.RequiredNestedMessage.class,
+ factory.createSchema(Proto2Message.RequiredNestedMessage.class));
+ protobuf.registerSchemaOverride(
+ Proto2Message.FieldRequiredGroup88.class,
+ factory.createSchema(Proto2Message.FieldRequiredGroup88.class));
+ protobuf.registerSchemaOverride(Proto2Empty.class, factory.createSchema(Proto2Empty.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageWithExtensions.class, factory.createSchema(Proto2MessageWithExtensions.class));
+ protobuf.registerSchemaOverride(
+ Proto2Testing.FieldGroup49.class, factory.createSchema(Proto2Testing.FieldGroup49.class));
+ protobuf.registerSchemaOverride(
+ Proto2Testing.FieldGroupList51.class,
+ factory.createSchema(Proto2Testing.FieldGroupList51.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageWithMaps.class, factory.createSchema(Proto2MessageWithMaps.class));
+ }
+
+ private static void registerProto3Schemas() {
+ Protobuf protobuf = Protobuf.getInstance();
+ ManifestSchemaFactory factory = new ManifestSchemaFactory();
+ protobuf.registerSchemaOverride(Proto3Message.class, factory.createSchema(Proto3Message.class));
+ protobuf.registerSchemaOverride(Proto3Empty.class, factory.createSchema(Proto3Empty.class));
+ protobuf.registerSchemaOverride(
+ Proto3MessageWithMaps.class, factory.createSchema(Proto3MessageWithMaps.class));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java b/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java
new file mode 100755
index 000000000..28a89d72a
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TestSchemasLite.java
@@ -0,0 +1,103 @@
+// 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.testing.Proto2TestingLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithExtensions;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3EmptyLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLiteWithMaps;
+
+/** Schemas to support testing. */
+public final class TestSchemasLite {
+
+ public static final Schema<Proto2MessageLite> genericProto2LiteSchema =
+ new ManifestSchemaFactory().createSchema(Proto2MessageLite.class);
+ public static final Schema<Proto3MessageLite> genericProto3LiteSchema =
+ new ManifestSchemaFactory().createSchema(Proto3MessageLite.class);
+
+ public static void registerGenericProto2LiteSchemas() {
+ registerProto2LiteSchemas();
+ }
+
+ public static void registerGenericProto3LiteSchemas() {
+ registerProto3LiteSchemas();
+ }
+
+ private static void registerProto2LiteSchemas() {
+ Protobuf protobuf = Protobuf.getInstance();
+ ManifestSchemaFactory factory = new ManifestSchemaFactory();
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.class, factory.createSchema(Proto2MessageLite.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.FieldGroup49.class,
+ factory.createSchema(Proto2MessageLite.FieldGroup49.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.FieldGroupList51.class,
+ factory.createSchema(Proto2MessageLite.FieldGroupList51.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.FieldGroup69.class,
+ factory.createSchema(Proto2MessageLite.FieldGroup69.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.RequiredNestedMessage.class,
+ factory.createSchema(Proto2MessageLite.RequiredNestedMessage.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLite.FieldRequiredGroup88.class,
+ factory.createSchema(Proto2MessageLite.FieldRequiredGroup88.class));
+ protobuf.registerSchemaOverride(
+ Proto2EmptyLite.class, factory.createSchema(Proto2EmptyLite.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLiteWithExtensions.class,
+ factory.createSchema(Proto2MessageLiteWithExtensions.class));
+ protobuf.registerSchemaOverride(
+ Proto2TestingLite.FieldGroup49.class,
+ factory.createSchema(Proto2TestingLite.FieldGroup49.class));
+ protobuf.registerSchemaOverride(
+ Proto2TestingLite.FieldGroupList51.class,
+ factory.createSchema(Proto2TestingLite.FieldGroupList51.class));
+ protobuf.registerSchemaOverride(
+ Proto2MessageLiteWithMaps.class, factory.createSchema(Proto2MessageLiteWithMaps.class));
+ }
+
+ private static void registerProto3LiteSchemas() {
+ Protobuf protobuf = Protobuf.getInstance();
+ ManifestSchemaFactory factory = new ManifestSchemaFactory();
+ protobuf.registerSchemaOverride(
+ Proto3MessageLite.class, factory.createSchema(Proto3MessageLite.class));
+ protobuf.registerSchemaOverride(
+ Proto3EmptyLite.class, factory.createSchema(Proto3EmptyLite.class));
+ protobuf.registerSchemaOverride(
+ Proto3MessageLiteWithMaps.class, factory.createSchema(Proto3MessageLiteWithMaps.class));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index 2fad0b957..3ed124348 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -132,6 +132,9 @@ public class TextFormatTest extends TestCase {
+ " i: 456\n"
+ "}\n";
+ private final TextFormat.Parser parserAllowingUnknownFields =
+ TextFormat.Parser.newBuilder().setAllowUnknownFields(true).build();
+
private final TextFormat.Parser parserAllowingUnknownExtensions =
TextFormat.Parser.newBuilder().setAllowUnknownExtensions(true).build();
@@ -502,6 +505,7 @@ public class TextFormatTest extends TestCase {
assertEquals(2, builder.getOptionalInt64());
}
+
private void assertParseError(String error, String text) {
// Test merge().
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -521,6 +525,22 @@ public class TextFormatTest extends TestCase {
}
}
+ private void assertParseErrorWithUnknownFields(String error, String text) {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ try {
+ parserAllowingUnknownFields.merge(text, TestUtil.getFullExtensionRegistry(), builder);
+ fail("Expected parse exception.");
+ } catch (TextFormat.ParseException e) {
+ assertEquals(error, e.getMessage());
+ }
+ }
+
+ private TestAllTypes assertParseSuccessWithUnknownFields(String text)
+ throws TextFormat.ParseException {
+ TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+ parserAllowingUnknownFields.merge(text, TestUtil.getFullExtensionRegistry(), builder);
+ return builder.build();
+ }
private void assertParseErrorWithUnknownExtensions(String error, String text) {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -1223,6 +1243,7 @@ public class TextFormatTest extends TestCase {
// Set to allow unknown fields
TextFormat.Parser parser =
TextFormat.Parser.newBuilder()
+ .setAllowUnknownFields(true)
.setParseInfoTreeBuilder(treeBuilder)
.build();
diff --git a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
deleted file mode 100644
index a947d271b..000000000
--- a/java/core/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
+++ /dev/null
@@ -1,601 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc. All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package com.google.protobuf;
-
-import static junit.framework.TestCase.assertEquals;
-
-import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
-import com.google.protobuf.UnittestLite.TestAllTypesLite;
-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.TestPackedExtensions;
-import protobuf_unittest.UnittestProto.TestPackedTypes;
-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 java.util.Arrays;
-import java.util.Map;
-import junit.framework.TestCase;
-
-/**
- * Tests for {@link UnknownFieldSetLite}.
- *
- * @author dweis@google.com (Daniel Weis)
- */
-public class UnknownFieldSetLiteTest extends TestCase {
- @Override
- public void setUp() throws Exception {
- allFields = TestUtil.getAllSet();
- allFieldsData = allFields.toByteString();
- emptyMessage = TestEmptyMessage.parseFrom(allFieldsData);
- unknownFields = emptyMessage.getUnknownFields();
- }
-
- TestAllTypes allFields;
- ByteString allFieldsData;
-
- // Constructs a protocol buffer which contains fields with all the same
- // numbers as allFieldsData except that each field is some other wire
- // type.
- private 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();
- }
-
- // An empty message that has been parsed from allFieldsData. So, it has
- // unknown fields of every type.
- TestEmptyMessage emptyMessage;
- UnknownFieldSet unknownFields;
-
- 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 testHashCodeAfterDeserialization() throws IOException {
- Foo foo = Foo.newBuilder().setValue(2).build();
-
- Foo fooDeserialized = Foo.parseFrom(foo.toByteArray());
-
- assertEquals(fooDeserialized, foo);
- assertEquals(foo.hashCode(), fooDeserialized.hashCode());
- }
-
- public void testNewInstanceHashCode() {
- UnknownFieldSetLite emptyFieldSet = UnknownFieldSetLite.getDefaultInstance();
- UnknownFieldSetLite paddedFieldSet = UnknownFieldSetLite.newInstance();
-
- assertEquals(emptyFieldSet, paddedFieldSet);
- assertEquals(emptyFieldSet.hashCode(), paddedFieldSet.hashCode());
- }
-
- 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());
- }
-
- 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/java/core/src/test/java/com/google/protobuf/Utf8Test.java b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
new file mode 100755
index 000000000..bc3c98510
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Utf8Test.java
@@ -0,0 +1,232 @@
+// 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.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.regex.Pattern;
+import junit.framework.TestCase;
+
+/** Unit tests for {@link Utf8}. */
+public class Utf8Test extends TestCase {
+ private static final int NUM_CHARS = 16384;
+
+ private static final Utf8.Processor safeProcessor = new Utf8.SafeProcessor();
+ private static final Utf8.Processor unsafeProcessor = new Utf8.UnsafeProcessor();
+
+ public void testEncode() {
+ assertEncoding(randomString(0x80));
+ assertEncoding(randomString(0x90));
+ assertEncoding(randomString(0x800));
+ assertEncoding(randomString(0x10000));
+ assertEncoding(randomString(0x10ffff));
+ }
+
+ public void testEncode_insufficientSpace() {
+ assertEncoding_insufficientSpace(randomString(0x80));
+ assertEncoding_insufficientSpace(randomString(0x90));
+ assertEncoding_insufficientSpace(randomString(0x800));
+ assertEncoding_insufficientSpace(randomString(0x10000));
+ assertEncoding_insufficientSpace(randomString(0x10ffff));
+ }
+
+ public void testValid() {
+ assertIsValid(new byte[] {(byte) 0xE0, (byte) 0xB9, (byte) 0x96}, true);
+ assertIsValid(new byte[] {(byte) 0xF0, (byte) 0xB2, (byte) 0x83, (byte) 0xBC}, true);
+ }
+
+ public void testOverlongIsInvalid() {
+ assertIsValid(new byte[] {(byte) 0xC0, (byte) 0x81}, false);
+ assertIsValid(new byte[] {(byte) 0xE0, (byte) 0x81, (byte) 0x81}, false);
+ assertIsValid(new byte[] {(byte) 0xF0, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false);
+ }
+
+ public void testMaxCodepointExceeded() {
+ // byte1 > 0xF4
+ assertIsValid(new byte[] {(byte) 0xF5, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false);
+ }
+
+ public void testInvalidSurrogateCodepoint() {
+ assertIsValid(new byte[] {(byte) 0xED, (byte) 0xA1, (byte) 0x81}, false);
+
+ // byte1 == 0xF0 && byte2 < 0x90
+ assertIsValid(new byte[] {(byte) 0xF0, (byte) 0x81, (byte) 0x81, (byte) 0x81}, false);
+ // byte1 == 0xF4 && byte2 > 0x8F
+ assertIsValid(new byte[] {(byte) 0xF4, (byte) 0x90, (byte) 0x81, (byte) 0x81}, false);
+ }
+
+ private static String randomString(int maxCodePoint) {
+ final long seed = 99;
+ final Random rnd = new Random(seed);
+ StringBuilder sb = new StringBuilder();
+ for (int j = 0; j < NUM_CHARS; j++) {
+ int codePoint;
+ do {
+ codePoint = rnd.nextInt(maxCodePoint);
+ } while (Utf8Utils.isSurrogate(codePoint));
+ sb.appendCodePoint(codePoint);
+ }
+ return sb.toString();
+ }
+
+ private static void assertIsValid(byte[] data, boolean valid) {
+ assertEquals("isValidUtf8[ARRAY]", valid, safeProcessor.isValidUtf8(data, 0, data.length));
+ assertEquals(
+ "isValidUtf8[ARRAY_UNSAFE]", valid, unsafeProcessor.isValidUtf8(data, 0, data.length));
+
+ ByteBuffer buffer = ByteBuffer.wrap(data);
+ assertEquals(
+ "isValidUtf8[NIO_HEAP]",
+ valid,
+ safeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining()));
+
+ // Direct buffers.
+ buffer = ByteBuffer.allocateDirect(data.length);
+ buffer.put(data);
+ buffer.flip();
+ assertEquals(
+ "isValidUtf8[NIO_DEFAULT]",
+ valid,
+ safeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining()));
+ assertEquals(
+ "isValidUtf8[NIO_UNSAFE]",
+ valid,
+ unsafeProcessor.isValidUtf8(buffer, buffer.position(), buffer.remaining()));
+ }
+
+ private static void assertEncoding(String message) {
+ byte[] expected = message.getBytes(Internal.UTF_8);
+ byte[] output = encodeToByteArray(message, expected.length, safeProcessor);
+ assertTrue("encodeUtf8[ARRAY]", Arrays.equals(expected, output));
+
+ output = encodeToByteArray(message, expected.length, unsafeProcessor);
+ assertTrue("encodeUtf8[ARRAY_UNSAFE]", Arrays.equals(expected, output));
+
+ output = encodeToByteBuffer(message, expected.length, false, safeProcessor);
+ assertTrue("encodeUtf8[NIO_HEAP]", Arrays.equals(expected, output));
+
+ output = encodeToByteBuffer(message, expected.length, true, safeProcessor);
+ assertTrue("encodeUtf8[NIO_DEFAULT]", Arrays.equals(expected, output));
+
+ output = encodeToByteBuffer(message, expected.length, true, unsafeProcessor);
+ assertTrue("encodeUtf8[NIO_UNSAFE]", Arrays.equals(expected, output));
+ }
+
+ private void assertEncoding_insufficientSpace(String message) {
+ final int length = message.length() - 1;
+ Class<ArrayIndexOutOfBoundsException> clazz = ArrayIndexOutOfBoundsException.class;
+
+ try {
+ encodeToByteArray(message, length, safeProcessor);
+ fail("Expected " + clazz.getSimpleName());
+ } catch (Throwable t) {
+ // Expected
+ assertExceptionType(t, clazz);
+ // byte[] + safeProcessor will not exit early. We can't match the message since we don't
+ // know which char/index due to random input.
+ }
+
+ try {
+ encodeToByteArray(message, length, unsafeProcessor);
+ fail("Expected " + clazz.getSimpleName());
+ } catch (Throwable t) {
+ assertExceptionType(t, clazz);
+ // byte[] + unsafeProcessor will exit early, so we have can match the message.
+ assertExceptionMessage(t, length);
+ }
+
+ try {
+ encodeToByteBuffer(message, length, false, safeProcessor);
+ fail("Expected " + clazz.getSimpleName());
+ } catch (Throwable t) {
+ // Expected
+ assertExceptionType(t, clazz);
+ // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
+ // know which char/index due to random input.
+ }
+
+ try {
+ encodeToByteBuffer(message, length, true, safeProcessor);
+ fail("Expected " + clazz.getSimpleName());
+ } catch (Throwable t) {
+ // Expected
+ assertExceptionType(t, clazz);
+ // ByteBuffer + safeProcessor will not exit early. We can't match the message since we don't
+ // know which char/index due to random input.
+ }
+
+ try {
+ encodeToByteBuffer(message, length, true, unsafeProcessor);
+ fail("Expected " + clazz.getSimpleName());
+ } catch (Throwable t) {
+ // Expected
+ assertExceptionType(t, clazz);
+ // Direct ByteBuffer + unsafeProcessor will exit early if it's not on Android, so we can
+ // match the message. On Android, a direct ByteBuffer will have hasArray() being true and
+ // it will take a different code path and produces a different message.
+ if (!Android.isOnAndroidDevice()) {
+ assertExceptionMessage(t, length);
+ }
+ }
+ }
+
+ private static byte[] encodeToByteArray(String message, int length, Utf8.Processor processor) {
+ byte[] output = new byte[length];
+ processor.encodeUtf8(message, output, 0, output.length);
+ return output;
+ }
+
+ private static byte[] encodeToByteBuffer(
+ String message, int length, boolean direct, Utf8.Processor processor) {
+ ByteBuffer buffer = direct ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
+
+ processor.encodeUtf8(message, buffer);
+ buffer.flip();
+
+ byte[] output = new byte[buffer.remaining()];
+ buffer.get(output);
+ return output;
+ }
+
+ private <T extends Throwable> void assertExceptionType(Throwable t, Class<T> expected) {
+ if (!expected.isAssignableFrom(t.getClass())) {
+ fail("Expected " + expected.getSimpleName() + ", but found " + t.getClass().getSimpleName());
+ }
+ }
+
+ private void assertExceptionMessage(Throwable t, int index) {
+ String pattern = "Failed writing (.) at index " + index;
+ assertTrue(
+ t.getMessage() + " does not match pattern " + pattern,
+ Pattern.matches(pattern, t.getMessage()));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/Utf8Utils.java b/java/core/src/test/java/com/google/protobuf/Utf8Utils.java
new file mode 100755
index 000000000..dbd3d3961
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/Utf8Utils.java
@@ -0,0 +1,193 @@
+// 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.Character.MIN_HIGH_SURROGATE;
+import static java.lang.Character.MIN_LOW_SURROGATE;
+import static java.lang.Character.MIN_SURROGATE;
+
+import java.util.Random;
+
+/** Utilities for benchmarking UTF-8. */
+final class Utf8Utils {
+ private Utf8Utils() {}
+
+ static class MaxCodePoint {
+ final int value;
+
+ /**
+ * Convert the input string to a code point. Accepts regular decimal numerals, hex strings, and
+ * some symbolic names meaningful to humans.
+ */
+ private static int decode(String userFriendly) {
+ try {
+ return Integer.decode(userFriendly);
+ } catch (NumberFormatException ignored) {
+ if (userFriendly.matches("(?i)(?:American|English|ASCII)")) {
+ // 1-byte UTF-8 sequences - "American" ASCII text
+ return 0x80;
+ } else if (userFriendly.matches("(?i)(?:Danish|Latin|Western.*European)")) {
+ // Mostly 1-byte UTF-8 sequences, mixed with occasional 2-byte
+ // sequences - "Western European" text
+ return 0x90;
+ } else if (userFriendly.matches("(?i)(?:Greek|Cyrillic|European|ISO.?8859)")) {
+ // Mostly 2-byte UTF-8 sequences - "European" text
+ return 0x800;
+ } else if (userFriendly.matches("(?i)(?:Chinese|Han|Asian|BMP)")) {
+ // Mostly 3-byte UTF-8 sequences - "Asian" text
+ return Character.MIN_SUPPLEMENTARY_CODE_POINT;
+ } else if (userFriendly.matches("(?i)(?:Cuneiform|rare|exotic|supplementary.*)")) {
+ // Mostly 4-byte UTF-8 sequences - "rare exotic" text
+ return Character.MAX_CODE_POINT;
+ } else {
+ throw new IllegalArgumentException("Can't decode codepoint " + userFriendly);
+ }
+ }
+ }
+
+ public static MaxCodePoint valueOf(String userFriendly) {
+ return new MaxCodePoint(userFriendly);
+ }
+
+ public MaxCodePoint(String userFriendly) {
+ value = decode(userFriendly);
+ }
+ }
+
+ /**
+ * The Utf8 distribution of real data. The distribution is an array with length 4.
+ * "distribution[i]" means the total number of characters who are encoded with (i + 1) bytes.
+ *
+ * <p>GMM_UTF8_DISTRIBUTION is the distribution of gmm data set. GSR_UTF8_DISTRIBUTION is the
+ * distribution of gsreq/gsresp data set
+ */
+ public enum Utf8Distribution {
+ GMM_UTF8_DISTRIBUTION {
+ @Override
+ public int[] getDistribution() {
+ return new int[] {53059, 104, 0, 0};
+ }
+ },
+ GSR_UTF8_DISTRIBUTION {
+ @Override
+ public int[] getDistribution() {
+ return new int[] {119458, 74, 2706, 0};
+ }
+ };
+
+ public abstract int[] getDistribution();
+ }
+
+ /**
+ * Creates an array of random strings.
+ *
+ * @param stringCount the number of strings to be created.
+ * @param charCount the number of characters per string.
+ * @param maxCodePoint the maximum code point for the characters in the strings.
+ * @return an array of random strings.
+ */
+ static String[] randomStrings(int stringCount, int charCount, MaxCodePoint maxCodePoint) {
+ final long seed = 99;
+ final Random rnd = new Random(seed);
+ String[] strings = new String[stringCount];
+ for (int i = 0; i < stringCount; i++) {
+ strings[i] = randomString(rnd, charCount, maxCodePoint);
+ }
+ return strings;
+ }
+
+ /**
+ * Creates a random string
+ *
+ * @param rnd the random generator.
+ * @param charCount the number of characters per string.
+ * @param maxCodePoint the maximum code point for the characters in the strings.
+ */
+ static String randomString(Random rnd, int charCount, MaxCodePoint maxCodePoint) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < charCount; i++) {
+ int codePoint;
+ do {
+ codePoint = rnd.nextInt(maxCodePoint.value);
+ } while (Utf8Utils.isSurrogate(codePoint));
+ sb.appendCodePoint(codePoint);
+ }
+ return sb.toString();
+ }
+
+ /** Character.isSurrogate was added in Java SE 7. */
+ static boolean isSurrogate(int c) {
+ return Character.MIN_HIGH_SURROGATE <= c && c <= Character.MAX_LOW_SURROGATE;
+ }
+
+ /**
+ * Creates an array of random strings according to UTF8 distribution.
+ *
+ * @param stringCount the number of strings to be created.
+ * @param charCount the number of characters per string.
+ */
+ static String[] randomStringsWithDistribution(
+ int stringCount, int charCount, Utf8Distribution utf8Distribution) {
+ final int[] distribution = utf8Distribution.getDistribution();
+ for (int i = 0; i < 3; i++) {
+ distribution[i + 1] += distribution[i];
+ }
+ final long seed = 99;
+ final Random rnd = new Random(seed);
+ String[] strings = new String[stringCount];
+ for (int i = 0; i < stringCount; i++) {
+ StringBuilder sb = new StringBuilder();
+ for (int j = 0; j < charCount; j++) {
+ int codePoint;
+ do {
+ codePoint = rnd.nextInt(distribution[3]);
+ if (codePoint < distribution[0]) {
+ // 1 bytes
+ sb.append(0x7F);
+ } else if (codePoint < distribution[1]) {
+ // 2 bytes
+ sb.append(0x7FF);
+ } else if (codePoint < distribution[2]) {
+ // 3 bytes
+ sb.append(MIN_SURROGATE - 1);
+ } else {
+ // 4 bytes
+ sb.append(MIN_HIGH_SURROGATE);
+ sb.append(MIN_LOW_SURROGATE);
+ }
+ } while (Utf8Utils.isSurrogate(codePoint));
+ sb.appendCodePoint(codePoint);
+ }
+ strings[i] = sb.toString();
+ }
+ return strings;
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java b/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java
new file mode 100755
index 000000000..a725d413f
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java
@@ -0,0 +1,1023 @@
+// 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.optionalForeignEnumExtensionLite;
+
+import com.google.protobuf.UnittestLite.ForeignEnumLite;
+import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
+import com.google.protobuf.UnittestLite.TestPackedExtensionsLite;
+import map_test.MapForProto2TestProto;
+import map_test.MapTestProto.TestMap;
+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.TestExtensionInsideTable;
+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 proto3_unittest.UnittestProto3;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+import junit.framework.TestCase;
+
+public class WireFormatLiteTest extends TestCase {
+ 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 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 registryLite = TestUtilLite.getExtensionRegistryLite();
+
+ TestAllExtensionsLite message2 = TestAllExtensionsLite.parseFrom(rawBytes, registryLite);
+ TestUtil.assertAllExtensionsSet(message2);
+ message2 = TestAllExtensionsLite.parseFrom(message.toByteArray(), registryLite);
+ TestUtil.assertAllExtensionsSet(message2);
+ }
+
+ 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);
+ message2 = TestPackedExtensionsLite.parseFrom(message.toByteArray(), registry);
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ 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();
+
+ ExtensionRegistryLite 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();
+
+ ExtensionRegistryLite registry = TestUtil.getExtensionRegistry();
+
+ TestPackedExtensions message2 = TestPackedExtensions.parseFrom(rawBytes, registry);
+
+ TestUtil.assertPackedExtensionsSet(message2);
+ }
+
+ 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.
+ assertNull(TestAllTypes.parseDelimitedFrom(input));
+ }
+
+ private ExtensionRegistryLite getTestFieldOrderingsRegistry() {
+ ExtensionRegistryLite result = ExtensionRegistryLite.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);
+ }
+
+ private static ExtensionRegistryLite getTestExtensionInsideTableRegistry() {
+ ExtensionRegistryLite result = ExtensionRegistryLite.newInstance();
+ result.add(UnittestProto.testExtensionInsideTableExtension);
+ return result;
+ }
+
+ public void testExtensionInsideTable() throws Exception {
+ // Make sure the extension within the range of table is parsed correctly in experimental
+ // runtime.
+ TestExtensionInsideTable source =
+ TestExtensionInsideTable.newBuilder()
+ .setField1(1)
+ .setExtension(UnittestProto.testExtensionInsideTableExtension, 23)
+ .build();
+ TestExtensionInsideTable dest =
+ TestExtensionInsideTable.parseFrom(
+ source.toByteString(), getTestExtensionInsideTableRegistry());
+ assertEquals(source, dest);
+ }
+
+ private static final int UNKNOWN_TYPE_ID = 1550055;
+ private static final int TYPE_ID_1 = 1545008;
+ private static final int TYPE_ID_2 = 1547769;
+
+ public void testSerializeMessageSetEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(true);
+ }
+
+ public void testSerializeMessageSetNotEagerly() throws Exception {
+ testSerializeMessageSetWithFlag(false);
+ }
+
+ private void testSerializeMessageSetWithFlag(boolean eagerParsing) throws Exception {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CodedOutputStream output = CodedOutputStream.newInstance(byteArrayOutputStream);
+ output.writeRawMessageSetExtension(UNKNOWN_TYPE_ID, ByteString.copyFromUtf8("bar"));
+ output.flush();
+ byte[] messageSetBytes = byteArrayOutputStream.toByteArray();
+
+ 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())
+ .mergeFrom(messageSetBytes)
+ .build();
+
+ ByteString data = messageSet.toByteString();
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet raw = RawMessageSet.parseFrom(data);
+
+ 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());
+ assertEquals(123, message1.getI());
+
+ TestMessageSetExtension2 message2 =
+ TestMessageSetExtension2.parseFrom(raw.getItem(1).getMessage());
+ 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);
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.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());
+ }
+
+ public void testParseMessageSetExtensionEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(true);
+ }
+
+ public void testParseMessageSetExtensionNotEagerly() throws Exception {
+ testParseMessageSetExtensionWithFlag(false);
+ }
+
+ private void testParseMessageSetExtensionWithFlag(boolean eagerParsing) throws Exception {
+ ExtensionRegistryLite.setEagerlyParseMessageSets(eagerParsing);
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int typeId1 = 1545008;
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(typeId1)
+ .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);
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int typeId1 = 1545008;
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(typeId1)
+ .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);
+ ExtensionRegistryLite extensionRegistry = ExtensionRegistryLite.newInstance();
+ extensionRegistry.add(TestMessageSetExtension1.messageSetExtension);
+
+ // Set up a RawMessageSet with a known messages.
+ int typeId1 = 1545008;
+ RawMessageSet raw =
+ RawMessageSet.newBuilder()
+ .addItem(
+ RawMessageSet.Item.newBuilder()
+ .setTypeId(typeId1)
+ .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 (RawMessageSet.Item item : items) {
+ 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());
+ }
+
+ private void assertInvalidWireFormat(
+ MessageLite defaultInstance, byte[] data, int offset, int length) {
+ // Test all combinations: (builder vs parser) x (byte[] vs. InputStream).
+ try {
+ defaultInstance.newBuilderForType().mergeFrom(data, offset, length);
+ fail("Expected exception");
+ } catch (InvalidProtocolBufferException e) {
+ // Pass.
+ }
+ try {
+ defaultInstance.getParserForType().parseFrom(data, offset, length);
+ fail("Expected exception");
+ } catch (InvalidProtocolBufferException e) {
+ // Pass.
+ }
+ try {
+ InputStream input = new ByteArrayInputStream(data, offset, length);
+ defaultInstance.newBuilderForType().mergeFrom(input);
+ fail("Expected exception");
+ } catch (IOException e) {
+ // Pass.
+ }
+ try {
+ InputStream input = new ByteArrayInputStream(data, offset, length);
+ defaultInstance.getParserForType().parseFrom(input);
+ fail("Expected exception");
+ } catch (IOException e) {
+ // Pass.
+ }
+ }
+
+ private void assertInvalidWireFormat(MessageLite defaultInstance, byte[] data) {
+ assertInvalidWireFormat(defaultInstance, data, 0, data.length);
+ }
+
+ private void assertInvalidWireFormat(byte[] data) {
+ assertInvalidWireFormat(TestAllTypes.getDefaultInstance(), data);
+ assertInvalidWireFormat(UnittestProto3.TestAllTypes.getDefaultInstance(), data);
+ }
+
+ public void testParserRejectInvalidTag() throws Exception {
+ byte[] invalidTags =
+ new byte[] {
+ // Zero tag is not allowed.
+ 0,
+ // Invalid wire types.
+ (byte) WireFormat.makeTag(1, 6),
+ (byte) WireFormat.makeTag(1, 7),
+ // Field number 0 is not allowed.
+ (byte) WireFormat.makeTag(0, WireFormat.WIRETYPE_VARINT),
+ };
+ for (byte invalidTag : invalidTags) {
+ // Add a trailing 0 to make sure the parsing actually fails on the tag.
+ byte[] data = new byte[] {invalidTag, 0};
+ assertInvalidWireFormat(data);
+
+ // Invalid tag in an unknown group field.
+ data =
+ new byte[] {
+ (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_START_GROUP),
+ invalidTag,
+ 0,
+ (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_END_GROUP),
+ };
+ assertInvalidWireFormat(data);
+
+ // Invalid tag in a MessageSet item.
+ data =
+ new byte[] {
+ (byte) WireFormat.MESSAGE_SET_ITEM_TAG,
+ (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG,
+ 100, // TYPE_ID = 100
+ (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG,
+ 0, // empty payload
+ invalidTag,
+ 0,
+ (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG,
+ };
+ assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data);
+
+ // Invalid tag inside a MessageSet item's unknown group.
+ data =
+ new byte[] {
+ (byte) WireFormat.MESSAGE_SET_ITEM_TAG,
+ (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG,
+ 100, // TYPE_ID = 100
+ (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG,
+ 0, // empty payload
+ (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP),
+ invalidTag,
+ 0,
+ (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_END_GROUP),
+ (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG,
+ };
+ assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data);
+
+ // Invalid tag inside a map field.
+ data =
+ new byte[] {
+ (byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 2, invalidTag, 0,
+ };
+ assertInvalidWireFormat(TestMap.getDefaultInstance(), data);
+ }
+ }
+
+ public void testUnmatchedGroupTag() throws Exception {
+ int startTag = WireFormat.makeTag(16, WireFormat.WIRETYPE_START_GROUP);
+ byte[] data =
+ new byte[] {
+ (byte) ((startTag & 0x7F) | 0x80), (byte) ((startTag >>> 7) & 0x7F),
+ };
+ assertInvalidWireFormat(data);
+
+ // Unmatched group tags inside a MessageSet item.
+ data =
+ new byte[] {
+ (byte) WireFormat.MESSAGE_SET_ITEM_TAG,
+ (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG,
+ 100, // TYPE_ID = 100
+ (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG,
+ 0, // empty payload
+ (byte) WireFormat.makeTag(4, WireFormat.WIRETYPE_START_GROUP),
+ };
+ assertInvalidWireFormat(TestMessageSet.getDefaultInstance(), data);
+ }
+
+ private void assertAccepted(MessageLite defaultInstance, byte[] data) throws Exception {
+ MessageLite message1 = defaultInstance.newBuilderForType().mergeFrom(data).build();
+ MessageLite message2 = defaultInstance.getParserForType().parseFrom(data);
+ MessageLite message3 =
+ defaultInstance.newBuilderForType().mergeFrom(new ByteArrayInputStream(data)).build();
+ MessageLite message4 =
+ defaultInstance.getParserForType().parseFrom(new ByteArrayInputStream(data));
+ assertEquals(message1, message2);
+ assertEquals(message2, message3);
+ assertEquals(message3, message4);
+ }
+
+ public void testUnmatchedWireType() throws Exception {
+ // Build a payload with all fields from 1 to 128 being varints. Parsing it into TestAllTypes
+ // or other message types should succeed even though the wire type doesn't match for some
+ // fields.
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
+ for (int i = 1; i <= 128; i++) {
+ codedOutput.writeInt32(i, 0);
+ }
+ codedOutput.flush();
+ byte[] data = output.toByteArray();
+ // It can be parsed into any message type that doesn't have required fields.
+ assertAccepted(TestAllTypes.getDefaultInstance(), data);
+ assertAccepted(UnittestProto3.TestAllTypes.getDefaultInstance(), data);
+ assertAccepted(TestMap.getDefaultInstance(), data);
+ assertAccepted(MapForProto2TestProto.TestMap.getDefaultInstance(), data);
+ }
+
+ public void testParseTruncatedPackedFields() throws Exception {
+ TestPackedTypes all = TestUtil.getPackedSet();
+ TestPackedTypes[] messages =
+ new TestPackedTypes[] {
+ TestPackedTypes.newBuilder().addAllPackedInt32(all.getPackedInt32List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedInt64(all.getPackedInt64List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedUint32(all.getPackedUint32List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedUint64(all.getPackedUint64List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedSint32(all.getPackedSint32List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedSint64(all.getPackedSint64List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedFixed32(all.getPackedFixed32List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedFixed64(all.getPackedFixed64List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedSfixed32(all.getPackedSfixed32List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedSfixed64(all.getPackedSfixed64List()).build(),
+ TestPackedTypes.newBuilder().addAllPackedFloat(all.getPackedFloatList()).build(),
+ TestPackedTypes.newBuilder().addAllPackedDouble(all.getPackedDoubleList()).build(),
+ TestPackedTypes.newBuilder().addAllPackedEnum(all.getPackedEnumList()).build(),
+ };
+ for (TestPackedTypes message : messages) {
+ byte[] data = message.toByteArray();
+ // Parsing truncated payload should fail.
+ for (int i = 1; i < data.length; i++) {
+ assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data, 0, i);
+ }
+ }
+ }
+
+ public void testParsePackedFieldsWithIncorrectLength() throws Exception {
+ // Set the length-prefix to 1 with a 4-bytes payload to test what happens when reading a packed
+ // element moves the reading position past the given length limit. It should result in an
+ // InvalidProtocolBufferException but an implementation may forget to check it especially for
+ // packed varint fields.
+ byte[] data =
+ new byte[] {
+ 0,
+ 0, // first two bytes is reserved for the tag.
+ 1, // length is 1
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x01, // a 4-bytes varint
+ };
+ // All fields that can read a 4-bytes varint (all varint fields and fixed 32-bit fields).
+ int[] fieldNumbers =
+ new int[] {
+ TestPackedTypes.PACKED_INT32_FIELD_NUMBER,
+ TestPackedTypes.PACKED_INT64_FIELD_NUMBER,
+ TestPackedTypes.PACKED_UINT32_FIELD_NUMBER,
+ TestPackedTypes.PACKED_UINT64_FIELD_NUMBER,
+ TestPackedTypes.PACKED_SINT32_FIELD_NUMBER,
+ TestPackedTypes.PACKED_SINT64_FIELD_NUMBER,
+ TestPackedTypes.PACKED_FIXED32_FIELD_NUMBER,
+ TestPackedTypes.PACKED_SFIXED32_FIELD_NUMBER,
+ TestPackedTypes.PACKED_FLOAT_FIELD_NUMBER,
+ TestPackedTypes.PACKED_BOOL_FIELD_NUMBER,
+ TestPackedTypes.PACKED_ENUM_FIELD_NUMBER,
+ };
+ for (int number : fieldNumbers) {
+ // Set the tag.
+ data[0] =
+ (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80);
+ data[1] =
+ (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F);
+ assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data);
+ }
+
+ // Data with 8-bytes payload to test some fixed 64-bit fields.
+ byte[] data8Bytes =
+ new byte[] {
+ 0,
+ 0, // first two bytes is reserved for the tag.
+ 1, // length is 1
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x80,
+ (byte) 0x01, // a 8-bytes varint
+ };
+ // All fields that can only read 8-bytes data.
+ int[] fieldNumbers8Bytes =
+ new int[] {
+ TestPackedTypes.PACKED_FIXED64_FIELD_NUMBER,
+ TestPackedTypes.PACKED_SFIXED64_FIELD_NUMBER,
+ TestPackedTypes.PACKED_DOUBLE_FIELD_NUMBER,
+ };
+ for (int number : fieldNumbers8Bytes) {
+ // Set the tag.
+ data8Bytes[0] =
+ (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) & 0x7F) | 0x80);
+ data8Bytes[1] =
+ (byte) ((WireFormat.makeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED) >>> 7) & 0x7F);
+ assertInvalidWireFormat(TestPackedTypes.getDefaultInstance(), data8Bytes);
+ }
+ }
+
+ public void testParseVarintMinMax() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .setOptionalInt32(Integer.MIN_VALUE)
+ .addRepeatedInt32(Integer.MAX_VALUE)
+ .setOptionalInt64(Long.MIN_VALUE)
+ .addRepeatedInt64(Long.MAX_VALUE)
+ .build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(Integer.MIN_VALUE, parsed.getOptionalInt32());
+ assertEquals(Integer.MAX_VALUE, parsed.getRepeatedInt32(0));
+ assertEquals(Long.MIN_VALUE, parsed.getOptionalInt64());
+ assertEquals(Long.MAX_VALUE, parsed.getRepeatedInt64(0));
+ }
+
+ public void testParseAllVarintBits() throws Exception {
+ for (int i = 0; i < 32; i++) {
+ final int value = 1 << i;
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(value).build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(value, parsed.getOptionalInt32());
+ }
+ for (int i = 0; i < 64; i++) {
+ final long value = 1L << i;
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt64(value).build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(value, parsed.getOptionalInt64());
+ }
+ }
+
+ public void testParseEmptyUnknownLengthDelimitedField() throws Exception {
+ byte[] data =
+ new byte[] {(byte) WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED), 0};
+ TestAllTypes parsed = TestAllTypes.parseFrom(data);
+ assertTrue(Arrays.equals(data, parsed.toByteArray()));
+ }
+
+ public void testParseEmptyString() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals("", parsed.getOptionalString());
+ }
+
+ public void testParseEmptyStringProto3() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalString("").build();
+ // Note that we are parsing from a proto2 proto to a proto3 proto because empty string field is
+ // not serialized in proto3.
+ UnittestProto3.TestAllTypes parsed =
+ UnittestProto3.TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals("", parsed.getOptionalString());
+ }
+
+ public void testParseEmptyBytes() throws Exception {
+ TestAllTypes message = TestAllTypes.newBuilder().setOptionalBytes(ByteString.EMPTY).build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(ByteString.EMPTY, parsed.getOptionalBytes());
+ }
+
+ public void testParseEmptyRepeatedStringField() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .addRepeatedString("")
+ .addRepeatedString("")
+ .addRepeatedString("0")
+ .build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(3, parsed.getRepeatedStringCount());
+ assertEquals("", parsed.getRepeatedString(0));
+ assertEquals("", parsed.getRepeatedString(1));
+ assertEquals("0", parsed.getRepeatedString(2));
+ }
+
+ public void testParseEmptyRepeatedStringFieldProto3() throws Exception {
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .addRepeatedString("")
+ .addRepeatedString("")
+ .addRepeatedString("0")
+ .addRepeatedBytes(ByteString.EMPTY)
+ .build();
+ UnittestProto3.TestAllTypes parsed =
+ UnittestProto3.TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(3, parsed.getRepeatedStringCount());
+ assertEquals("", parsed.getRepeatedString(0));
+ assertEquals("", parsed.getRepeatedString(1));
+ assertEquals("0", parsed.getRepeatedString(2));
+ }
+
+ public void testParseEmptyRepeatedBytesField() throws Exception {
+ ByteString oneByte = ByteString.copyFrom(new byte[] {1});
+ TestAllTypes message =
+ TestAllTypes.newBuilder()
+ .addRepeatedBytes(ByteString.EMPTY)
+ .addRepeatedBytes(ByteString.EMPTY)
+ .addRepeatedBytes(oneByte)
+ .build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(3, parsed.getRepeatedBytesCount());
+ assertEquals(ByteString.EMPTY, parsed.getRepeatedBytes(0));
+ assertEquals(ByteString.EMPTY, parsed.getRepeatedBytes(1));
+ assertEquals(oneByte, parsed.getRepeatedBytes(2));
+ }
+
+ public void testSkipUnknownFieldInMessageSetItem() throws Exception {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ // MessageSet item's start tag.
+ output.write((byte) WireFormat.MESSAGE_SET_ITEM_TAG);
+ // Put all field types into the item.
+ TestUtil.getAllSet().writeTo(output);
+ // Closing the item with the real payload and closing tag.
+ output.write(
+ new byte[] {
+ (byte) WireFormat.MESSAGE_SET_TYPE_ID_TAG,
+ 100, // TYPE_ID = 100
+ (byte) WireFormat.MESSAGE_SET_MESSAGE_TAG,
+ 0, // empty payload
+ (byte) WireFormat.MESSAGE_SET_ITEM_END_TAG,
+ });
+ byte[] data = output.toByteArray();
+ TestMessageSet parsed = TestMessageSet.parseFrom(data);
+
+ // Convert to RawMessageSet for inspection.
+ RawMessageSet raw = RawMessageSet.parseFrom(parsed.toByteArray());
+ assertEquals(1, raw.getItemCount());
+ assertEquals(100, raw.getItem(0).getTypeId());
+ assertEquals(0, raw.getItem(0).getMessage().size());
+ }
+
+ public void testProto2UnknownEnumValuesInOptionalField() throws Exception {
+ // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with
+ // unknown enum values
+ UnittestProto3.TestAllTypes message =
+ UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertFalse(parsed.hasOptionalNestedEnum());
+ // Make sure unknown enum values are preserved.
+ UnittestProto3.TestAllTypes actual =
+ UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray());
+ assertEquals(4321, actual.getOptionalNestedEnumValue());
+ }
+
+ public void testProto2UnknownEnumValuesInRepeatedField() throws Exception {
+ // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with
+ // unknown enum values
+ UnittestProto3.TestAllTypes message =
+ UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build();
+ TestAllTypes parsed = TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(0, parsed.getRepeatedNestedEnumCount());
+ // Make sure unknown enum values are preserved.
+ UnittestProto3.TestAllTypes actual =
+ UnittestProto3.TestAllTypes.parseFrom(parsed.toByteArray());
+ assertEquals(1, actual.getRepeatedNestedEnumCount());
+ assertEquals(5432, actual.getRepeatedNestedEnumValue(0));
+ }
+
+ public void testProto2UnknownEnumValuesInMapField() throws Exception {
+ // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with
+ // unknown enum values
+ TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build();
+ MapForProto2TestProto.TestMap parsed =
+ MapForProto2TestProto.TestMap.parseFrom(message.toByteArray());
+ assertEquals(0, parsed.getInt32ToEnumFieldMap().size());
+ // Make sure unknown enum values are preserved.
+ TestMap actual = TestMap.parseFrom(parsed.toByteArray());
+ assertEquals(1, actual.getInt32ToEnumFieldMap().size());
+ assertEquals(4321, actual.getInt32ToEnumFieldValueOrThrow(1));
+ }
+
+ public void testProto2UnknownEnumValuesInOneof() throws Exception {
+ // Proto2 doesn't allow setting unknown enum values so we use proto3 to build a message with
+ // unknown enum values
+ UnittestProto3.TestOneof2 message =
+ UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build();
+ TestOneof2 parsed = TestOneof2.parseFrom(message.toByteArray());
+ assertFalse(parsed.hasFooEnum());
+ // Make sure unknown enum values are preserved.
+ UnittestProto3.TestOneof2 actual = UnittestProto3.TestOneof2.parseFrom(parsed.toByteArray());
+ assertEquals(1234, actual.getFooEnumValue());
+ }
+
+ public void testProto2UnknownEnumValuesInExtension() throws Exception {
+ ExtensionRegistryLite extensionRegistry = TestUtilLite.getExtensionRegistryLite();
+ // Raw bytes for "[.optional_foreign_enum_extension_lite]: 10"
+ final byte[] rawBytes = new byte[]{-80, 1, 10};
+ TestAllExtensionsLite testAllExtensionsLite =
+ TestAllExtensionsLite.parseFrom(rawBytes, extensionRegistry);
+ assertEquals(ForeignEnumLite.FOREIGN_LITE_FOO,
+ testAllExtensionsLite.getExtension(optionalForeignEnumExtensionLite));
+ final byte[] resultRawBytes = testAllExtensionsLite.toByteArray();
+ assertEquals(rawBytes.length, resultRawBytes.length);
+ for (int i = 0; i < rawBytes.length; i++) {
+ assertEquals(rawBytes[i], resultRawBytes[i]);
+ }
+ }
+
+ public void testProto3UnknownEnumValuesInOptionalField() throws Exception {
+ UnittestProto3.TestAllTypes message =
+ UnittestProto3.TestAllTypes.newBuilder().setOptionalNestedEnumValue(4321).build();
+ UnittestProto3.TestAllTypes parsed =
+ UnittestProto3.TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(4321, parsed.getOptionalNestedEnumValue());
+ }
+
+ public void testProto3UnknownEnumValuesInRepeatedField() throws Exception {
+ UnittestProto3.TestAllTypes message =
+ UnittestProto3.TestAllTypes.newBuilder().addRepeatedNestedEnumValue(5432).build();
+ UnittestProto3.TestAllTypes parsed =
+ UnittestProto3.TestAllTypes.parseFrom(message.toByteArray());
+ assertEquals(1, parsed.getRepeatedNestedEnumCount());
+ assertEquals(5432, parsed.getRepeatedNestedEnumValue(0));
+ }
+
+ public void testProto3UnknownEnumValuesInMapField() throws Exception {
+ TestMap message = TestMap.newBuilder().putInt32ToEnumFieldValue(1, 4321).build();
+ TestMap parsed = TestMap.parseFrom(message.toByteArray());
+ assertEquals(1, parsed.getInt32ToEnumFieldMap().size());
+ assertEquals(4321, parsed.getInt32ToEnumFieldValueOrThrow(1));
+ }
+
+ public void testProto3UnknownEnumValuesInOneof() throws Exception {
+ UnittestProto3.TestOneof2 message =
+ UnittestProto3.TestOneof2.newBuilder().setFooEnumValue(1234).build();
+ UnittestProto3.TestOneof2 parsed = UnittestProto3.TestOneof2.parseFrom(message.toByteArray());
+ assertEquals(1234, parsed.getFooEnumValue());
+ }
+
+ public void testProto3MessageFieldMergeBehavior() throws Exception {
+ UnittestProto3.NestedTestAllTypes message1 =
+ UnittestProto3.NestedTestAllTypes.newBuilder()
+ .setPayload(
+ UnittestProto3.TestAllTypes.newBuilder()
+ .setOptionalInt32(1234)
+ .setOptionalInt64(5678))
+ .build();
+ UnittestProto3.NestedTestAllTypes message2 =
+ UnittestProto3.NestedTestAllTypes.newBuilder()
+ .setPayload(
+ UnittestProto3.TestAllTypes.newBuilder()
+ .setOptionalInt32(4321)
+ .setOptionalUint32(8765))
+ .build();
+
+ UnittestProto3.NestedTestAllTypes merged =
+ UnittestProto3.NestedTestAllTypes.newBuilder()
+ .mergeFrom(message1.toByteArray())
+ .mergeFrom(message2.toByteArray())
+ .build();
+ // Field values coming later in the stream override earlier values.
+ assertEquals(4321, merged.getPayload().getOptionalInt32());
+ // Field values present in either message should be present in the merged result.
+ assertEquals(5678, merged.getPayload().getOptionalInt64());
+ assertEquals(8765, merged.getPayload().getOptionalUint32());
+ }
+
+ public void testMergeFromPartialByteArray() throws Exception {
+ byte[] data = TestUtil.getAllSet().toByteArray();
+ byte[] dataWithPaddings = new byte[data.length + 2];
+ System.arraycopy(data, 0, dataWithPaddings, 1, data.length);
+ // Parsing will fail if the builder (or parser) interprets offset or length incorrectly.
+ TestAllTypes.newBuilder().mergeFrom(dataWithPaddings, 1, data.length);
+ TestAllTypes.parser().parseFrom(dataWithPaddings, 1, data.length);
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java b/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java
new file mode 100755
index 000000000..4a3c7647f
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.wrapperstest.WrappersTestProto.TopLevelMessage;
+import junit.framework.TestCase;
+
+public class WrappersLiteOfMethodTest extends TestCase {
+
+ public void testOf() throws Exception {
+ TopLevelMessage.Builder builder = TopLevelMessage.newBuilder();
+ builder.setFieldDouble(DoubleValue.of(2.333));
+ builder.setFieldFloat(FloatValue.of(2.333f));
+ builder.setFieldInt32(Int32Value.of(2333));
+ builder.setFieldInt64(Int64Value.of(23333333333333L));
+ builder.setFieldUint32(UInt32Value.of(2333));
+ builder.setFieldUint64(UInt64Value.of(23333333333333L));
+ builder.setFieldBool(BoolValue.of(true));
+ builder.setFieldString(StringValue.of("23333"));
+ builder.setFieldBytes(BytesValue.of(ByteString.wrap("233".getBytes(Internal.UTF_8))));
+
+ TopLevelMessage message = builder.build();
+ assertTrue(2.333 == message.getFieldDouble().getValue());
+ assertTrue(2.333f == message.getFieldFloat().getValue());
+ assertTrue(2333 == message.getFieldInt32().getValue());
+ assertTrue(23333333333333L == message.getFieldInt64().getValue());
+ assertTrue(2333 == message.getFieldUint32().getValue());
+ assertTrue(23333333333333L == message.getFieldUint64().getValue());
+ assertTrue(true == message.getFieldBool().getValue());
+ assertTrue(message.getFieldString().getValue().equals("23333"));
+ assertTrue(message.getFieldBytes().getValue().toStringUtf8().equals("233"));
+ }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java b/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java
new file mode 100755
index 000000000..f0d662d0c
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java
@@ -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.
+
+package com.google.protobuf;
+
+import com.google.protobuf.wrapperstest.WrappersTestProto.TopLevelMessage;
+import junit.framework.TestCase;
+
+public class WrappersOfMethodTest extends TestCase {
+
+ public void testOf() throws Exception {
+ TopLevelMessage.Builder builder = TopLevelMessage.newBuilder();
+ builder.setFieldDouble(DoubleValue.of(2.333));
+ builder.setFieldFloat(FloatValue.of(2.333f));
+ builder.setFieldInt32(Int32Value.of(2333));
+ builder.setFieldInt64(Int64Value.of(23333333333333L));
+ builder.setFieldUint32(UInt32Value.of(2333));
+ builder.setFieldUint64(UInt64Value.of(23333333333333L));
+ builder.setFieldBool(BoolValue.of(true));
+ builder.setFieldString(StringValue.of("23333"));
+ builder.setFieldBytes(BytesValue.of(ByteString.wrap("233".getBytes(Internal.UTF_8))));
+
+ TopLevelMessage message = builder.build();
+ assertTrue(2.333 == message.getFieldDouble().getValue());
+ assertTrue(2.333f == message.getFieldFloat().getValue());
+ assertTrue(2333 == message.getFieldInt32().getValue());
+ assertTrue(23333333333333L == message.getFieldInt64().getValue());
+ assertTrue(2333 == message.getFieldUint32().getValue());
+ assertTrue(23333333333333L == message.getFieldUint64().getValue());
+ assertTrue(true == message.getFieldBool().getValue());
+ assertTrue(message.getFieldString().getValue().equals("23333"));
+ assertTrue(message.getFieldBytes().getValue().toStringUtf8().equals("233"));
+ }
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto b/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto
new file mode 100755
index 000000000..ce78b34c6
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/cached_field_size_test.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.
+
+// A regression test for b/74087933
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option optimize_for = CODE_SIZE;
+option java_multiple_files = true;
+
+import "google/protobuf/unittest.proto";
+import "google/protobuf/unittest_proto3.proto";
+
+message TestCachedFieldSizeMessage {
+ optional protobuf_unittest.TestPackedTypes proto2_child = 1;
+ optional proto3_unittest.TestPackedTypes proto3_child = 2;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto b/java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.proto
new file mode 100755
index 000000000..f985ab0f5
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/message_lite_extension_util_test.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.
+
+// Proto definitions used to test MessageLiteExtensionUtil
+syntax = "proto2";
+
+package protobuf_unittest;
+
+option java_outer_classname = "MessageLiteExtensionTestProtos";
+
+message Car {
+ optional string make = 1;
+ extensions 1000 to max;
+}
+
+extend Car {
+ optional bool turbo = 1001;
+ optional bool self_driving = 1002;
+ optional string plate = 9999;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/nested_extension.proto b/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
index 037040b5b..2da6d08e3 100644
--- a/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
+++ b/java/core/src/test/proto/com/google/protobuf/nested_extension.proto
@@ -35,10 +35,10 @@
syntax = "proto2";
-import "com/google/protobuf/non_nested_extension.proto";
-
package protobuf_unittest;
+import "com/google/protobuf/non_nested_extension.proto";
+
message MyNestedExtension {
extend MessageToBeExtended {
diff --git a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
index 40d0f1905..024097cb5 100644
--- a/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
+++ b/java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto
@@ -38,10 +38,10 @@ syntax = "proto2";
package protobuf_unittest;
-option optimize_for = LITE_RUNTIME;
-
import "com/google/protobuf/non_nested_extension_lite.proto";
+option optimize_for = LITE_RUNTIME;
+
message MyNestedExtensionLite {
extend MessageLiteToBeExtended {
optional MessageLiteToBeExtended recursiveExtensionLite = 3;
diff --git a/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto b/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto
new file mode 100755
index 000000000..7935322b7
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/packed_field_test.proto
@@ -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.
+
+syntax = "proto3";
+
+package packed_field_test;
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "PackedFieldTestProto";
+
+message TestAllTypes {
+ enum NestedEnum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ }
+
+ 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 NestedEnum repeated_nested_enum = 51;
+}
+
+message TestUnpackedTypes {
+ repeated int32 repeated_int32 = 1 [packed = false];
+ repeated int64 repeated_int64 = 2 [packed = false];
+ repeated uint32 repeated_uint32 = 3 [packed = false];
+ repeated uint64 repeated_uint64 = 4 [packed = false];
+ repeated sint32 repeated_sint32 = 5 [packed = false];
+ repeated sint64 repeated_sint64 = 6 [packed = false];
+ repeated fixed32 repeated_fixed32 = 7 [packed = false];
+ repeated fixed64 repeated_fixed64 = 8 [packed = false];
+ repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
+ repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+ repeated float repeated_float = 11 [packed = false];
+ repeated double repeated_double = 12 [packed = false];
+ repeated bool repeated_bool = 13 [packed = false];
+ repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto
new file mode 100755
index 000000000..005a911d9
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto
@@ -0,0 +1,429 @@
+// 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.
+
+// LINT: ALLOW_GROUPS
+syntax = "proto2";
+
+option java_package = "com.google.protobuf.testing";
+option java_outer_classname = "Proto2Testing";
+package protobuf.experimental;
+
+
+message Proto2SpecialFieldName {
+ optional double regular_name = 1;
+ optional int32 cached_size = 2;
+ optional int64 serialized_size = 3;
+ optional string class = 4;
+}
+
+message Proto2Message {
+
+ enum TestEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ }
+
+ optional double field_double_1 = 1;
+ optional float field_float_2 = 2;
+ optional int64 field_int64_3 = 3;
+ optional uint64 field_uint64_4 = 4;
+ optional int32 field_int32_5 = 5;
+ optional fixed64 field_fixed64_6 = 6;
+ optional fixed32 field_fixed32_7 = 7;
+ optional bool field_bool_8 = 8;
+ optional string field_string_9 = 9;
+ optional Proto2Message field_message_10 = 10;
+ optional bytes field_bytes_11 = 11;
+ optional uint32 field_uint32_12 = 12;
+ optional TestEnum field_enum_13 = 13;
+ optional sfixed32 field_sfixed32_14 = 14;
+ optional sfixed64 field_sfixed64_15 = 15;
+ optional sint32 field_sint32_16 = 16;
+ optional sint64 field_sint64_17 = 17;
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto2Message field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated TestEnum field_enum_list_packed_44 = 44 [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+ optional group FieldGroup49 = 49 {
+ optional int32 field_int32_50 = 50;
+ }
+ repeated group FieldGroupList51 = 51 {
+ optional int32 field_int32_52 = 52;
+ }
+ oneof test_oneof {
+ double field_double_53 = 53;
+ float field_float_54 = 54;
+ int64 field_int64_55 = 55;
+ uint64 field_uint64_56 = 56;
+ int32 field_int32_57 = 57;
+ fixed64 field_fixed64_58 = 58;
+ fixed32 field_fixed32_59 = 59;
+ bool field_bool_60 = 60;
+ string field_string_61 = 61;
+ Proto2Message field_message_62 = 62;
+ bytes field_bytes_63 = 63;
+ uint32 field_uint32_64 = 64;
+ sfixed32 field_sfixed32_65 = 65;
+ sfixed64 field_sfixed64_66 = 66;
+ sint32 field_sint32_67 = 67;
+ sint64 field_sint64_68 = 68;
+ group FieldGroup69 = 69 {
+ optional int32 field_int32_70 = 70;
+ }
+ }
+
+ message RequiredNestedMessage {
+ optional int32 value = 1;
+ }
+
+ required double field_required_double_71 = 71;
+ required float field_required_float_72 = 72;
+ required int64 field_required_int64_73 = 73;
+ required uint64 field_required_uint64_74 = 74;
+ required int32 field_required_int32_75 = 75;
+ required fixed64 field_required_fixed64_76 = 76;
+ required fixed32 field_required_fixed32_77 = 77;
+ required bool field_required_bool_78 = 78;
+ required string field_required_string_79 = 79;
+ required RequiredNestedMessage field_required_message_80 = 80;
+ required bytes field_required_bytes_81 = 81;
+ required uint32 field_required_uint32_82 = 82;
+ required TestEnum field_required_enum_83 = 83;
+ required sfixed32 field_required_sfixed32_84 = 84;
+ required sfixed64 field_required_sfixed64_85 = 85;
+ required sint32 field_required_sint32_86 = 86;
+ required sint64 field_required_sint64_87 = 87;
+ required group FieldRequiredGroup88 = 88 {
+ optional int32 field_int32_89 = 89;
+ }
+}
+
+message Proto2Empty {}
+
+message Proto2MessageWithExtensions {
+ extensions 1 to 10000;
+}
+
+extend Proto2MessageWithExtensions {
+ optional double field_double_1 = 1;
+ optional float field_float_2 = 2;
+ optional int64 field_int64_3 = 3;
+ optional uint64 field_uint64_4 = 4;
+ optional int32 field_int32_5 = 5;
+ optional fixed64 field_fixed64_6 = 6;
+ optional fixed32 field_fixed32_7 = 7;
+ optional bool field_bool_8 = 8;
+ optional string field_string_9 = 9;
+ optional Proto2Message field_message_10 = 10;
+ optional bytes field_bytes_11 = 11;
+ optional uint32 field_uint32_12 = 12;
+ optional Proto2Message.TestEnum field_enum_13 = 13;
+ optional sfixed32 field_sfixed32_14 = 14;
+ optional sfixed64 field_sfixed64_15 = 15;
+ optional sint32 field_sint32_16 = 16;
+ optional sint64 field_sint64_17 = 17;
+
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto2Message field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated Proto2Message.TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated Proto2Message.TestEnum field_enum_list_packed_44 = 44
+ [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+
+ optional group FieldGroup49 = 49 {
+ optional int32 field_int32_50 = 50;
+ }
+
+ repeated group FieldGroupList51 = 51 {
+ optional int32 field_int32_52 = 52;
+ }
+}
+
+message Proto2MessageWithMaps {
+ map<bool, bool> field_map_bool_bool_1 = 1;
+ map<bool, bytes> field_map_bool_bytes_2 = 2;
+ map<bool, double> field_map_bool_double_3 = 3;
+ map<bool, Proto2Message.TestEnum> field_map_bool_enum_4 = 4;
+ map<bool, fixed32> field_map_bool_fixed32_5 = 5;
+ map<bool, fixed64> field_map_bool_fixed64_6 = 6;
+ map<bool, float> field_map_bool_float_7 = 7;
+ map<bool, int32> field_map_bool_int32_8 = 8;
+ map<bool, int64> field_map_bool_int64_9 = 9;
+ map<bool, Proto2Message> field_map_bool_message_10 = 10;
+ map<bool, sfixed32> field_map_bool_sfixed32_11 = 11;
+ map<bool, sfixed64> field_map_bool_sfixed64_12 = 12;
+ map<bool, sint32> field_map_bool_sint32_13 = 13;
+ map<bool, sint64> field_map_bool_sint64_14 = 14;
+ map<bool, string> field_map_bool_string_15 = 15;
+ map<bool, uint32> field_map_bool_uint32_16 = 16;
+ map<bool, uint64> field_map_bool_uint64_17 = 17;
+ map<fixed32, bool> field_map_fixed32_bool_18 = 18;
+ map<fixed32, bytes> field_map_fixed32_bytes_19 = 19;
+ map<fixed32, double> field_map_fixed32_double_20 = 20;
+ map<fixed32, Proto2Message.TestEnum> field_map_fixed32_enum_21 = 21;
+ map<fixed32, fixed32> field_map_fixed32_fixed32_22 = 22;
+ map<fixed32, fixed64> field_map_fixed32_fixed64_23 = 23;
+ map<fixed32, float> field_map_fixed32_float_24 = 24;
+ map<fixed32, int32> field_map_fixed32_int32_25 = 25;
+ map<fixed32, int64> field_map_fixed32_int64_26 = 26;
+ map<fixed32, Proto2Message> field_map_fixed32_message_27 = 27;
+ map<fixed32, sfixed32> field_map_fixed32_sfixed32_28 = 28;
+ map<fixed32, sfixed64> field_map_fixed32_sfixed64_29 = 29;
+ map<fixed32, sint32> field_map_fixed32_sint32_30 = 30;
+ map<fixed32, sint64> field_map_fixed32_sint64_31 = 31;
+ map<fixed32, string> field_map_fixed32_string_32 = 32;
+ map<fixed32, uint32> field_map_fixed32_uint32_33 = 33;
+ map<fixed32, uint64> field_map_fixed32_uint64_34 = 34;
+ map<fixed64, bool> field_map_fixed64_bool_35 = 35;
+ map<fixed64, bytes> field_map_fixed64_bytes_36 = 36;
+ map<fixed64, double> field_map_fixed64_double_37 = 37;
+ map<fixed64, Proto2Message.TestEnum> field_map_fixed64_enum_38 = 38;
+ map<fixed64, fixed32> field_map_fixed64_fixed32_39 = 39;
+ map<fixed64, fixed64> field_map_fixed64_fixed64_40 = 40;
+ map<fixed64, float> field_map_fixed64_float_41 = 41;
+ map<fixed64, int32> field_map_fixed64_int32_42 = 42;
+ map<fixed64, int64> field_map_fixed64_int64_43 = 43;
+ map<fixed64, Proto2Message> field_map_fixed64_message_44 = 44;
+ map<fixed64, sfixed32> field_map_fixed64_sfixed32_45 = 45;
+ map<fixed64, sfixed64> field_map_fixed64_sfixed64_46 = 46;
+ map<fixed64, sint32> field_map_fixed64_sint32_47 = 47;
+ map<fixed64, sint64> field_map_fixed64_sint64_48 = 48;
+ map<fixed64, string> field_map_fixed64_string_49 = 49;
+ map<fixed64, uint32> field_map_fixed64_uint32_50 = 50;
+ map<fixed64, uint64> field_map_fixed64_uint64_51 = 51;
+ map<int32, bool> field_map_int32_bool_52 = 52;
+ map<int32, bytes> field_map_int32_bytes_53 = 53;
+ map<int32, double> field_map_int32_double_54 = 54;
+ map<int32, Proto2Message.TestEnum> field_map_int32_enum_55 = 55;
+ map<int32, fixed32> field_map_int32_fixed32_56 = 56;
+ map<int32, fixed64> field_map_int32_fixed64_57 = 57;
+ map<int32, float> field_map_int32_float_58 = 58;
+ map<int32, int32> field_map_int32_int32_59 = 59;
+ map<int32, int64> field_map_int32_int64_60 = 60;
+ map<int32, Proto2Message> field_map_int32_message_61 = 61;
+ map<int32, sfixed32> field_map_int32_sfixed32_62 = 62;
+ map<int32, sfixed64> field_map_int32_sfixed64_63 = 63;
+ map<int32, sint32> field_map_int32_sint32_64 = 64;
+ map<int32, sint64> field_map_int32_sint64_65 = 65;
+ map<int32, string> field_map_int32_string_66 = 66;
+ map<int32, uint32> field_map_int32_uint32_67 = 67;
+ map<int32, uint64> field_map_int32_uint64_68 = 68;
+ map<int64, bool> field_map_int64_bool_69 = 69;
+ map<int64, bytes> field_map_int64_bytes_70 = 70;
+ map<int64, double> field_map_int64_double_71 = 71;
+ map<int64, Proto2Message.TestEnum> field_map_int64_enum_72 = 72;
+ map<int64, fixed32> field_map_int64_fixed32_73 = 73;
+ map<int64, fixed64> field_map_int64_fixed64_74 = 74;
+ map<int64, float> field_map_int64_float_75 = 75;
+ map<int64, int32> field_map_int64_int32_76 = 76;
+ map<int64, int64> field_map_int64_int64_77 = 77;
+ map<int64, Proto2Message> field_map_int64_message_78 = 78;
+ map<int64, sfixed32> field_map_int64_sfixed32_79 = 79;
+ map<int64, sfixed64> field_map_int64_sfixed64_80 = 80;
+ map<int64, sint32> field_map_int64_sint32_81 = 81;
+ map<int64, sint64> field_map_int64_sint64_82 = 82;
+ map<int64, string> field_map_int64_string_83 = 83;
+ map<int64, uint32> field_map_int64_uint32_84 = 84;
+ map<int64, uint64> field_map_int64_uint64_85 = 85;
+ map<sfixed32, bool> field_map_sfixed32_bool_86 = 86;
+ map<sfixed32, bytes> field_map_sfixed32_bytes_87 = 87;
+ map<sfixed32, double> field_map_sfixed32_double_88 = 88;
+ map<sfixed32, Proto2Message.TestEnum> field_map_sfixed32_enum_89 = 89;
+ map<sfixed32, fixed32> field_map_sfixed32_fixed32_90 = 90;
+ map<sfixed32, fixed64> field_map_sfixed32_fixed64_91 = 91;
+ map<sfixed32, float> field_map_sfixed32_float_92 = 92;
+ map<sfixed32, int32> field_map_sfixed32_int32_93 = 93;
+ map<sfixed32, int64> field_map_sfixed32_int64_94 = 94;
+ map<sfixed32, Proto2Message> field_map_sfixed32_message_95 = 95;
+ map<sfixed32, sfixed32> field_map_sfixed32_sfixed32_96 = 96;
+ map<sfixed32, sfixed64> field_map_sfixed32_sfixed64_97 = 97;
+ map<sfixed32, sint32> field_map_sfixed32_sint32_98 = 98;
+ map<sfixed32, sint64> field_map_sfixed32_sint64_99 = 99;
+ map<sfixed32, string> field_map_sfixed32_string_100 = 100;
+ map<sfixed32, uint32> field_map_sfixed32_uint32_101 = 101;
+ map<sfixed32, uint64> field_map_sfixed32_uint64_102 = 102;
+ map<sfixed64, bool> field_map_sfixed64_bool_103 = 103;
+ map<sfixed64, bytes> field_map_sfixed64_bytes_104 = 104;
+ map<sfixed64, double> field_map_sfixed64_double_105 = 105;
+ map<sfixed64, Proto2Message.TestEnum> field_map_sfixed64_enum_106 = 106;
+ map<sfixed64, fixed32> field_map_sfixed64_fixed32_107 = 107;
+ map<sfixed64, fixed64> field_map_sfixed64_fixed64_108 = 108;
+ map<sfixed64, float> field_map_sfixed64_float_109 = 109;
+ map<sfixed64, int32> field_map_sfixed64_int32_110 = 110;
+ map<sfixed64, int64> field_map_sfixed64_int64_111 = 111;
+ map<sfixed64, Proto2Message> field_map_sfixed64_message_112 = 112;
+ map<sfixed64, sfixed32> field_map_sfixed64_sfixed32_113 = 113;
+ map<sfixed64, sfixed64> field_map_sfixed64_sfixed64_114 = 114;
+ map<sfixed64, sint32> field_map_sfixed64_sint32_115 = 115;
+ map<sfixed64, sint64> field_map_sfixed64_sint64_116 = 116;
+ map<sfixed64, string> field_map_sfixed64_string_117 = 117;
+ map<sfixed64, uint32> field_map_sfixed64_uint32_118 = 118;
+ map<sfixed64, uint64> field_map_sfixed64_uint64_119 = 119;
+ map<sint32, bool> field_map_sint32_bool_120 = 120;
+ map<sint32, bytes> field_map_sint32_bytes_121 = 121;
+ map<sint32, double> field_map_sint32_double_122 = 122;
+ map<sint32, Proto2Message.TestEnum> field_map_sint32_enum_123 = 123;
+ map<sint32, fixed32> field_map_sint32_fixed32_124 = 124;
+ map<sint32, fixed64> field_map_sint32_fixed64_125 = 125;
+ map<sint32, float> field_map_sint32_float_126 = 126;
+ map<sint32, int32> field_map_sint32_int32_127 = 127;
+ map<sint32, int64> field_map_sint32_int64_128 = 128;
+ map<sint32, Proto2Message> field_map_sint32_message_129 = 129;
+ map<sint32, sfixed32> field_map_sint32_sfixed32_130 = 130;
+ map<sint32, sfixed64> field_map_sint32_sfixed64_131 = 131;
+ map<sint32, sint32> field_map_sint32_sint32_132 = 132;
+ map<sint32, sint64> field_map_sint32_sint64_133 = 133;
+ map<sint32, string> field_map_sint32_string_134 = 134;
+ map<sint32, uint32> field_map_sint32_uint32_135 = 135;
+ map<sint32, uint64> field_map_sint32_uint64_136 = 136;
+ map<sint64, bool> field_map_sint64_bool_137 = 137;
+ map<sint64, bytes> field_map_sint64_bytes_138 = 138;
+ map<sint64, double> field_map_sint64_double_139 = 139;
+ map<sint64, Proto2Message.TestEnum> field_map_sint64_enum_140 = 140;
+ map<sint64, fixed32> field_map_sint64_fixed32_141 = 141;
+ map<sint64, fixed64> field_map_sint64_fixed64_142 = 142;
+ map<sint64, float> field_map_sint64_float_143 = 143;
+ map<sint64, int32> field_map_sint64_int32_144 = 144;
+ map<sint64, int64> field_map_sint64_int64_145 = 145;
+ map<sint64, Proto2Message> field_map_sint64_message_146 = 146;
+ map<sint64, sfixed32> field_map_sint64_sfixed32_147 = 147;
+ map<sint64, sfixed64> field_map_sint64_sfixed64_148 = 148;
+ map<sint64, sint32> field_map_sint64_sint32_149 = 149;
+ map<sint64, sint64> field_map_sint64_sint64_150 = 150;
+ map<sint64, string> field_map_sint64_string_151 = 151;
+ map<sint64, uint32> field_map_sint64_uint32_152 = 152;
+ map<sint64, uint64> field_map_sint64_uint64_153 = 153;
+ map<string, bool> field_map_string_bool_154 = 154;
+ map<string, bytes> field_map_string_bytes_155 = 155;
+ map<string, double> field_map_string_double_156 = 156;
+ map<string, Proto2Message.TestEnum> field_map_string_enum_157 = 157;
+ map<string, fixed32> field_map_string_fixed32_158 = 158;
+ map<string, fixed64> field_map_string_fixed64_159 = 159;
+ map<string, float> field_map_string_float_160 = 160;
+ map<string, int32> field_map_string_int32_161 = 161;
+ map<string, int64> field_map_string_int64_162 = 162;
+ map<string, Proto2Message> field_map_string_message_163 = 163;
+ map<string, sfixed32> field_map_string_sfixed32_164 = 164;
+ map<string, sfixed64> field_map_string_sfixed64_165 = 165;
+ map<string, sint32> field_map_string_sint32_166 = 166;
+ map<string, sint64> field_map_string_sint64_167 = 167;
+ map<string, string> field_map_string_string_168 = 168;
+ map<string, uint32> field_map_string_uint32_169 = 169;
+ map<string, uint64> field_map_string_uint64_170 = 170;
+ map<uint32, bool> field_map_uint32_bool_171 = 171;
+ map<uint32, bytes> field_map_uint32_bytes_172 = 172;
+ map<uint32, double> field_map_uint32_double_173 = 173;
+ map<uint32, Proto2Message.TestEnum> field_map_uint32_enum_174 = 174;
+ map<uint32, fixed32> field_map_uint32_fixed32_175 = 175;
+ map<uint32, fixed64> field_map_uint32_fixed64_176 = 176;
+ map<uint32, float> field_map_uint32_float_177 = 177;
+ map<uint32, int32> field_map_uint32_int32_178 = 178;
+ map<uint32, int64> field_map_uint32_int64_179 = 179;
+ map<uint32, Proto2Message> field_map_uint32_message_180 = 180;
+ map<uint32, sfixed32> field_map_uint32_sfixed32_181 = 181;
+ map<uint32, sfixed64> field_map_uint32_sfixed64_182 = 182;
+ map<uint32, sint32> field_map_uint32_sint32_183 = 183;
+ map<uint32, sint64> field_map_uint32_sint64_184 = 184;
+ map<uint32, string> field_map_uint32_string_185 = 185;
+ map<uint32, uint32> field_map_uint32_uint32_186 = 186;
+ map<uint32, uint64> field_map_uint32_uint64_187 = 187;
+ map<uint64, bool> field_map_uint64_bool_188 = 188;
+ map<uint64, bytes> field_map_uint64_bytes_189 = 189;
+ map<uint64, double> field_map_uint64_double_190 = 190;
+ map<uint64, Proto2Message.TestEnum> field_map_uint64_enum_191 = 191;
+ map<uint64, fixed32> field_map_uint64_fixed32_192 = 192;
+ map<uint64, fixed64> field_map_uint64_fixed64_193 = 193;
+ map<uint64, float> field_map_uint64_float_194 = 194;
+ map<uint64, int32> field_map_uint64_int32_195 = 195;
+ map<uint64, int64> field_map_uint64_int64_196 = 196;
+ map<uint64, Proto2Message> field_map_uint64_message_197 = 197;
+ map<uint64, sfixed32> field_map_uint64_sfixed32_198 = 198;
+ map<uint64, sfixed64> field_map_uint64_sfixed64_199 = 199;
+ map<uint64, sint32> field_map_uint64_sint32_200 = 200;
+ map<uint64, sint64> field_map_uint64_sint64_201 = 201;
+ map<uint64, string> field_map_uint64_string_202 = 202;
+ map<uint64, uint32> field_map_uint64_uint32_203 = 203;
+ map<uint64, uint64> field_map_uint64_uint64_204 = 204;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto
new file mode 100755
index 000000000..8385dfdce
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto
@@ -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.
+
+// LINT: ALLOW_GROUPS
+syntax = "proto2";
+
+option java_package = "com.google.protobuf.testing";
+option java_outer_classname = "Proto2TestingLite";
+package protobuf.experimental.lite;
+
+
+message Proto2MessageLite {
+
+ enum TestEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ }
+
+ optional double field_double_1 = 1;
+ optional float field_float_2 = 2;
+ optional int64 field_int64_3 = 3;
+ optional uint64 field_uint64_4 = 4;
+ optional int32 field_int32_5 = 5;
+ optional fixed64 field_fixed64_6 = 6;
+ optional fixed32 field_fixed32_7 = 7;
+ optional bool field_bool_8 = 8;
+ optional string field_string_9 = 9;
+ optional Proto2MessageLite field_message_10 = 10;
+ optional bytes field_bytes_11 = 11;
+ optional uint32 field_uint32_12 = 12;
+ optional TestEnum field_enum_13 = 13;
+ optional sfixed32 field_sfixed32_14 = 14;
+ optional sfixed64 field_sfixed64_15 = 15;
+ optional sint32 field_sint32_16 = 16;
+ optional sint64 field_sint64_17 = 17;
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto2MessageLite field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated TestEnum field_enum_list_packed_44 = 44 [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+ optional group FieldGroup49 = 49 {
+ optional int32 field_int32_50 = 50;
+ }
+ repeated group FieldGroupList51 = 51 {
+ optional int32 field_int32_52 = 52;
+ }
+ oneof test_oneof {
+ double field_double_53 = 53;
+ float field_float_54 = 54;
+ int64 field_int64_55 = 55;
+ uint64 field_uint64_56 = 56;
+ int32 field_int32_57 = 57;
+ fixed64 field_fixed64_58 = 58;
+ fixed32 field_fixed32_59 = 59;
+ bool field_bool_60 = 60;
+ string field_string_61 = 61;
+ Proto2MessageLite field_message_62 = 62;
+ bytes field_bytes_63 = 63;
+ uint32 field_uint32_64 = 64;
+ sfixed32 field_sfixed32_65 = 65;
+ sfixed64 field_sfixed64_66 = 66;
+ sint32 field_sint32_67 = 67;
+ sint64 field_sint64_68 = 68;
+ group FieldGroup69 = 69 {
+ optional int32 field_int32_70 = 70;
+ }
+ }
+
+ message RequiredNestedMessage {
+ optional int32 value = 1;
+ }
+
+ required double field_required_double_71 = 71;
+ required float field_required_float_72 = 72;
+ required int64 field_required_int64_73 = 73;
+ required uint64 field_required_uint64_74 = 74;
+ required int32 field_required_int32_75 = 75;
+ required fixed64 field_required_fixed64_76 = 76;
+ required fixed32 field_required_fixed32_77 = 77;
+ required bool field_required_bool_78 = 78;
+ required string field_required_string_79 = 79;
+ required RequiredNestedMessage field_required_message_80 = 80;
+ required bytes field_required_bytes_81 = 81;
+ required uint32 field_required_uint32_82 = 82;
+ required TestEnum field_required_enum_83 = 83;
+ required sfixed32 field_required_sfixed32_84 = 84;
+ required sfixed64 field_required_sfixed64_85 = 85;
+ required sint32 field_required_sint32_86 = 86;
+ required sint64 field_required_sint64_87 = 87;
+ required group FieldRequiredGroup88 = 88 {
+ optional int32 field_int32_89 = 89;
+ }
+}
+
+message Proto2EmptyLite {}
+
+message Proto2MessageLiteWithExtensions {
+ extensions 1 to max;
+}
+
+extend Proto2MessageLiteWithExtensions {
+ optional double field_double_1 = 1;
+ optional float field_float_2 = 2;
+ optional int64 field_int64_3 = 3;
+ optional uint64 field_uint64_4 = 4;
+ optional int32 field_int32_5 = 5;
+ optional fixed64 field_fixed64_6 = 6;
+ optional fixed32 field_fixed32_7 = 7;
+ optional bool field_bool_8 = 8;
+ optional string field_string_9 = 9;
+ optional Proto2MessageLite field_message_10 = 10;
+ optional bytes field_bytes_11 = 11;
+ optional uint32 field_uint32_12 = 12;
+ optional Proto2MessageLite.TestEnum field_enum_13 = 13;
+ optional sfixed32 field_sfixed32_14 = 14;
+ optional sfixed64 field_sfixed64_15 = 15;
+ optional sint32 field_sint32_16 = 16;
+ optional sint64 field_sint64_17 = 17;
+
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto2MessageLite field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated Proto2MessageLite.TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated Proto2MessageLite.TestEnum field_enum_list_packed_44 = 44
+ [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+
+ optional group FieldGroup49 = 49 {
+ optional int32 field_int32_50 = 50;
+ }
+
+ repeated group FieldGroupList51 = 51 {
+ optional int32 field_int32_52 = 52;
+ }
+}
+
+message Proto2MessageLiteWithMaps {
+ map<bool, bool> field_map_bool_bool_1 = 1;
+ map<bool, bytes> field_map_bool_bytes_2 = 2;
+ map<bool, double> field_map_bool_double_3 = 3;
+ map<bool, Proto2MessageLite.TestEnum> field_map_bool_enum_4 = 4;
+ map<bool, fixed32> field_map_bool_fixed32_5 = 5;
+ map<bool, fixed64> field_map_bool_fixed64_6 = 6;
+ map<bool, float> field_map_bool_float_7 = 7;
+ map<bool, int32> field_map_bool_int32_8 = 8;
+ map<bool, int64> field_map_bool_int64_9 = 9;
+ map<bool, Proto2MessageLite> field_map_bool_message_10 = 10;
+ map<bool, sfixed32> field_map_bool_sfixed32_11 = 11;
+ map<bool, sfixed64> field_map_bool_sfixed64_12 = 12;
+ map<bool, sint32> field_map_bool_sint32_13 = 13;
+ map<bool, sint64> field_map_bool_sint64_14 = 14;
+ map<bool, string> field_map_bool_string_15 = 15;
+ map<bool, uint32> field_map_bool_uint32_16 = 16;
+ map<bool, uint64> field_map_bool_uint64_17 = 17;
+ map<fixed32, bool> field_map_fixed32_bool_18 = 18;
+ map<fixed32, bytes> field_map_fixed32_bytes_19 = 19;
+ map<fixed32, double> field_map_fixed32_double_20 = 20;
+ map<fixed32, Proto2MessageLite.TestEnum> field_map_fixed32_enum_21 = 21;
+ map<fixed32, fixed32> field_map_fixed32_fixed32_22 = 22;
+ map<fixed32, fixed64> field_map_fixed32_fixed64_23 = 23;
+ map<fixed32, float> field_map_fixed32_float_24 = 24;
+ map<fixed32, int32> field_map_fixed32_int32_25 = 25;
+ map<fixed32, int64> field_map_fixed32_int64_26 = 26;
+ map<fixed32, Proto2MessageLite> field_map_fixed32_message_27 = 27;
+ map<fixed32, sfixed32> field_map_fixed32_sfixed32_28 = 28;
+ map<fixed32, sfixed64> field_map_fixed32_sfixed64_29 = 29;
+ map<fixed32, sint32> field_map_fixed32_sint32_30 = 30;
+ map<fixed32, sint64> field_map_fixed32_sint64_31 = 31;
+ map<fixed32, string> field_map_fixed32_string_32 = 32;
+ map<fixed32, uint32> field_map_fixed32_uint32_33 = 33;
+ map<fixed32, uint64> field_map_fixed32_uint64_34 = 34;
+ map<fixed64, bool> field_map_fixed64_bool_35 = 35;
+ map<fixed64, bytes> field_map_fixed64_bytes_36 = 36;
+ map<fixed64, double> field_map_fixed64_double_37 = 37;
+ map<fixed64, Proto2MessageLite.TestEnum> field_map_fixed64_enum_38 = 38;
+ map<fixed64, fixed32> field_map_fixed64_fixed32_39 = 39;
+ map<fixed64, fixed64> field_map_fixed64_fixed64_40 = 40;
+ map<fixed64, float> field_map_fixed64_float_41 = 41;
+ map<fixed64, int32> field_map_fixed64_int32_42 = 42;
+ map<fixed64, int64> field_map_fixed64_int64_43 = 43;
+ map<fixed64, Proto2MessageLite> field_map_fixed64_message_44 = 44;
+ map<fixed64, sfixed32> field_map_fixed64_sfixed32_45 = 45;
+ map<fixed64, sfixed64> field_map_fixed64_sfixed64_46 = 46;
+ map<fixed64, sint32> field_map_fixed64_sint32_47 = 47;
+ map<fixed64, sint64> field_map_fixed64_sint64_48 = 48;
+ map<fixed64, string> field_map_fixed64_string_49 = 49;
+ map<fixed64, uint32> field_map_fixed64_uint32_50 = 50;
+ map<fixed64, uint64> field_map_fixed64_uint64_51 = 51;
+ map<int32, bool> field_map_int32_bool_52 = 52;
+ map<int32, bytes> field_map_int32_bytes_53 = 53;
+ map<int32, double> field_map_int32_double_54 = 54;
+ map<int32, Proto2MessageLite.TestEnum> field_map_int32_enum_55 = 55;
+ map<int32, fixed32> field_map_int32_fixed32_56 = 56;
+ map<int32, fixed64> field_map_int32_fixed64_57 = 57;
+ map<int32, float> field_map_int32_float_58 = 58;
+ map<int32, int32> field_map_int32_int32_59 = 59;
+ map<int32, int64> field_map_int32_int64_60 = 60;
+ map<int32, Proto2MessageLite> field_map_int32_message_61 = 61;
+ map<int32, sfixed32> field_map_int32_sfixed32_62 = 62;
+ map<int32, sfixed64> field_map_int32_sfixed64_63 = 63;
+ map<int32, sint32> field_map_int32_sint32_64 = 64;
+ map<int32, sint64> field_map_int32_sint64_65 = 65;
+ map<int32, string> field_map_int32_string_66 = 66;
+ map<int32, uint32> field_map_int32_uint32_67 = 67;
+ map<int32, uint64> field_map_int32_uint64_68 = 68;
+ map<int64, bool> field_map_int64_bool_69 = 69;
+ map<int64, bytes> field_map_int64_bytes_70 = 70;
+ map<int64, double> field_map_int64_double_71 = 71;
+ map<int64, Proto2MessageLite.TestEnum> field_map_int64_enum_72 = 72;
+ map<int64, fixed32> field_map_int64_fixed32_73 = 73;
+ map<int64, fixed64> field_map_int64_fixed64_74 = 74;
+ map<int64, float> field_map_int64_float_75 = 75;
+ map<int64, int32> field_map_int64_int32_76 = 76;
+ map<int64, int64> field_map_int64_int64_77 = 77;
+ map<int64, Proto2MessageLite> field_map_int64_message_78 = 78;
+ map<int64, sfixed32> field_map_int64_sfixed32_79 = 79;
+ map<int64, sfixed64> field_map_int64_sfixed64_80 = 80;
+ map<int64, sint32> field_map_int64_sint32_81 = 81;
+ map<int64, sint64> field_map_int64_sint64_82 = 82;
+ map<int64, string> field_map_int64_string_83 = 83;
+ map<int64, uint32> field_map_int64_uint32_84 = 84;
+ map<int64, uint64> field_map_int64_uint64_85 = 85;
+ map<sfixed32, bool> field_map_sfixed32_bool_86 = 86;
+ map<sfixed32, bytes> field_map_sfixed32_bytes_87 = 87;
+ map<sfixed32, double> field_map_sfixed32_double_88 = 88;
+ map<sfixed32, Proto2MessageLite.TestEnum> field_map_sfixed32_enum_89 = 89;
+ map<sfixed32, fixed32> field_map_sfixed32_fixed32_90 = 90;
+ map<sfixed32, fixed64> field_map_sfixed32_fixed64_91 = 91;
+ map<sfixed32, float> field_map_sfixed32_float_92 = 92;
+ map<sfixed32, int32> field_map_sfixed32_int32_93 = 93;
+ map<sfixed32, int64> field_map_sfixed32_int64_94 = 94;
+ map<sfixed32, Proto2MessageLite> field_map_sfixed32_message_95 = 95;
+ map<sfixed32, sfixed32> field_map_sfixed32_sfixed32_96 = 96;
+ map<sfixed32, sfixed64> field_map_sfixed32_sfixed64_97 = 97;
+ map<sfixed32, sint32> field_map_sfixed32_sint32_98 = 98;
+ map<sfixed32, sint64> field_map_sfixed32_sint64_99 = 99;
+ map<sfixed32, string> field_map_sfixed32_string_100 = 100;
+ map<sfixed32, uint32> field_map_sfixed32_uint32_101 = 101;
+ map<sfixed32, uint64> field_map_sfixed32_uint64_102 = 102;
+ map<sfixed64, bool> field_map_sfixed64_bool_103 = 103;
+ map<sfixed64, bytes> field_map_sfixed64_bytes_104 = 104;
+ map<sfixed64, double> field_map_sfixed64_double_105 = 105;
+ map<sfixed64, Proto2MessageLite.TestEnum> field_map_sfixed64_enum_106 = 106;
+ map<sfixed64, fixed32> field_map_sfixed64_fixed32_107 = 107;
+ map<sfixed64, fixed64> field_map_sfixed64_fixed64_108 = 108;
+ map<sfixed64, float> field_map_sfixed64_float_109 = 109;
+ map<sfixed64, int32> field_map_sfixed64_int32_110 = 110;
+ map<sfixed64, int64> field_map_sfixed64_int64_111 = 111;
+ map<sfixed64, Proto2MessageLite> field_map_sfixed64_message_112 = 112;
+ map<sfixed64, sfixed32> field_map_sfixed64_sfixed32_113 = 113;
+ map<sfixed64, sfixed64> field_map_sfixed64_sfixed64_114 = 114;
+ map<sfixed64, sint32> field_map_sfixed64_sint32_115 = 115;
+ map<sfixed64, sint64> field_map_sfixed64_sint64_116 = 116;
+ map<sfixed64, string> field_map_sfixed64_string_117 = 117;
+ map<sfixed64, uint32> field_map_sfixed64_uint32_118 = 118;
+ map<sfixed64, uint64> field_map_sfixed64_uint64_119 = 119;
+ map<sint32, bool> field_map_sint32_bool_120 = 120;
+ map<sint32, bytes> field_map_sint32_bytes_121 = 121;
+ map<sint32, double> field_map_sint32_double_122 = 122;
+ map<sint32, Proto2MessageLite.TestEnum> field_map_sint32_enum_123 = 123;
+ map<sint32, fixed32> field_map_sint32_fixed32_124 = 124;
+ map<sint32, fixed64> field_map_sint32_fixed64_125 = 125;
+ map<sint32, float> field_map_sint32_float_126 = 126;
+ map<sint32, int32> field_map_sint32_int32_127 = 127;
+ map<sint32, int64> field_map_sint32_int64_128 = 128;
+ map<sint32, Proto2MessageLite> field_map_sint32_message_129 = 129;
+ map<sint32, sfixed32> field_map_sint32_sfixed32_130 = 130;
+ map<sint32, sfixed64> field_map_sint32_sfixed64_131 = 131;
+ map<sint32, sint32> field_map_sint32_sint32_132 = 132;
+ map<sint32, sint64> field_map_sint32_sint64_133 = 133;
+ map<sint32, string> field_map_sint32_string_134 = 134;
+ map<sint32, uint32> field_map_sint32_uint32_135 = 135;
+ map<sint32, uint64> field_map_sint32_uint64_136 = 136;
+ map<sint64, bool> field_map_sint64_bool_137 = 137;
+ map<sint64, bytes> field_map_sint64_bytes_138 = 138;
+ map<sint64, double> field_map_sint64_double_139 = 139;
+ map<sint64, Proto2MessageLite.TestEnum> field_map_sint64_enum_140 = 140;
+ map<sint64, fixed32> field_map_sint64_fixed32_141 = 141;
+ map<sint64, fixed64> field_map_sint64_fixed64_142 = 142;
+ map<sint64, float> field_map_sint64_float_143 = 143;
+ map<sint64, int32> field_map_sint64_int32_144 = 144;
+ map<sint64, int64> field_map_sint64_int64_145 = 145;
+ map<sint64, Proto2MessageLite> field_map_sint64_message_146 = 146;
+ map<sint64, sfixed32> field_map_sint64_sfixed32_147 = 147;
+ map<sint64, sfixed64> field_map_sint64_sfixed64_148 = 148;
+ map<sint64, sint32> field_map_sint64_sint32_149 = 149;
+ map<sint64, sint64> field_map_sint64_sint64_150 = 150;
+ map<sint64, string> field_map_sint64_string_151 = 151;
+ map<sint64, uint32> field_map_sint64_uint32_152 = 152;
+ map<sint64, uint64> field_map_sint64_uint64_153 = 153;
+ map<string, bool> field_map_string_bool_154 = 154;
+ map<string, bytes> field_map_string_bytes_155 = 155;
+ map<string, double> field_map_string_double_156 = 156;
+ map<string, Proto2MessageLite.TestEnum> field_map_string_enum_157 = 157;
+ map<string, fixed32> field_map_string_fixed32_158 = 158;
+ map<string, fixed64> field_map_string_fixed64_159 = 159;
+ map<string, float> field_map_string_float_160 = 160;
+ map<string, int32> field_map_string_int32_161 = 161;
+ map<string, int64> field_map_string_int64_162 = 162;
+ map<string, Proto2MessageLite> field_map_string_message_163 = 163;
+ map<string, sfixed32> field_map_string_sfixed32_164 = 164;
+ map<string, sfixed64> field_map_string_sfixed64_165 = 165;
+ map<string, sint32> field_map_string_sint32_166 = 166;
+ map<string, sint64> field_map_string_sint64_167 = 167;
+ map<string, string> field_map_string_string_168 = 168;
+ map<string, uint32> field_map_string_uint32_169 = 169;
+ map<string, uint64> field_map_string_uint64_170 = 170;
+ map<uint32, bool> field_map_uint32_bool_171 = 171;
+ map<uint32, bytes> field_map_uint32_bytes_172 = 172;
+ map<uint32, double> field_map_uint32_double_173 = 173;
+ map<uint32, Proto2MessageLite.TestEnum> field_map_uint32_enum_174 = 174;
+ map<uint32, fixed32> field_map_uint32_fixed32_175 = 175;
+ map<uint32, fixed64> field_map_uint32_fixed64_176 = 176;
+ map<uint32, float> field_map_uint32_float_177 = 177;
+ map<uint32, int32> field_map_uint32_int32_178 = 178;
+ map<uint32, int64> field_map_uint32_int64_179 = 179;
+ map<uint32, Proto2MessageLite> field_map_uint32_message_180 = 180;
+ map<uint32, sfixed32> field_map_uint32_sfixed32_181 = 181;
+ map<uint32, sfixed64> field_map_uint32_sfixed64_182 = 182;
+ map<uint32, sint32> field_map_uint32_sint32_183 = 183;
+ map<uint32, sint64> field_map_uint32_sint64_184 = 184;
+ map<uint32, string> field_map_uint32_string_185 = 185;
+ map<uint32, uint32> field_map_uint32_uint32_186 = 186;
+ map<uint32, uint64> field_map_uint32_uint64_187 = 187;
+ map<uint64, bool> field_map_uint64_bool_188 = 188;
+ map<uint64, bytes> field_map_uint64_bytes_189 = 189;
+ map<uint64, double> field_map_uint64_double_190 = 190;
+ map<uint64, Proto2MessageLite.TestEnum> field_map_uint64_enum_191 = 191;
+ map<uint64, fixed32> field_map_uint64_fixed32_192 = 192;
+ map<uint64, fixed64> field_map_uint64_fixed64_193 = 193;
+ map<uint64, float> field_map_uint64_float_194 = 194;
+ map<uint64, int32> field_map_uint64_int32_195 = 195;
+ map<uint64, int64> field_map_uint64_int64_196 = 196;
+ map<uint64, Proto2MessageLite> field_map_uint64_message_197 = 197;
+ map<uint64, sfixed32> field_map_uint64_sfixed32_198 = 198;
+ map<uint64, sfixed64> field_map_uint64_sfixed64_199 = 199;
+ map<uint64, sint32> field_map_uint64_sint32_200 = 200;
+ map<uint64, sint64> field_map_uint64_sint64_201 = 201;
+ map<uint64, string> field_map_uint64_string_202 = 202;
+ map<uint64, uint32> field_map_uint64_uint32_203 = 203;
+ map<uint64, uint64> field_map_uint64_uint64_204 = 204;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/proto3_message.proto b/java/core/src/test/proto/com/google/protobuf/proto3_message.proto
new file mode 100755
index 000000000..01c7deb7c
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/proto3_message.proto
@@ -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.
+
+syntax = "proto3";
+
+option java_package = "com.google.protobuf.testing";
+option java_outer_classname = "Proto3Testing";
+package protobuf.experimental;
+
+message Proto3SpecialFieldName {
+ double regular_name = 1;
+ int32 cached_size = 2;
+ int64 serialized_size = 3;
+ string class = 4;
+}
+
+message Proto3Message {
+ enum TestEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ }
+
+ double field_double_1 = 1;
+ float field_float_2 = 2;
+ int64 field_int64_3 = 3;
+ uint64 field_uint64_4 = 4;
+ int32 field_int32_5 = 5;
+ fixed64 field_fixed64_6 = 6;
+ fixed32 field_fixed32_7 = 7;
+ bool field_bool_8 = 8;
+ string field_string_9 = 9;
+ Proto3Message field_message_10 = 10;
+ bytes field_bytes_11 = 11;
+ uint32 field_uint32_12 = 12;
+ TestEnum field_enum_13 = 13;
+ sfixed32 field_sfixed32_14 = 14;
+ sfixed64 field_sfixed64_15 = 15;
+ sint32 field_sint32_16 = 16;
+ sint64 field_sint64_17 = 17;
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto3Message field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated TestEnum field_enum_list_packed_44 = 44 [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+ oneof test_oneof {
+ double field_double_53 = 53;
+ float field_float_54 = 54;
+ int64 field_int64_55 = 55;
+ uint64 field_uint64_56 = 56;
+ int32 field_int32_57 = 57;
+ fixed64 field_fixed64_58 = 58;
+ fixed32 field_fixed32_59 = 59;
+ bool field_bool_60 = 60;
+ string field_string_61 = 61;
+ Proto3Message field_message_62 = 62;
+ bytes field_bytes_63 = 63;
+ uint32 field_uint32_64 = 64;
+ sfixed32 field_sfixed32_65 = 65;
+ sfixed64 field_sfixed64_66 = 66;
+ sint32 field_sint32_67 = 67;
+ sint64 field_sint64_68 = 68;
+ }
+}
+
+message Proto3Empty {}
+
+message Proto3MessageWithMaps {
+ map<bool, bool> field_map_bool_bool_1 = 1;
+ map<bool, bytes> field_map_bool_bytes_2 = 2;
+ map<bool, double> field_map_bool_double_3 = 3;
+ map<bool, Proto3Message.TestEnum> field_map_bool_enum_4 = 4;
+ map<bool, fixed32> field_map_bool_fixed32_5 = 5;
+ map<bool, fixed64> field_map_bool_fixed64_6 = 6;
+ map<bool, float> field_map_bool_float_7 = 7;
+ map<bool, int32> field_map_bool_int32_8 = 8;
+ map<bool, int64> field_map_bool_int64_9 = 9;
+ map<bool, Proto3Message> field_map_bool_message_10 = 10;
+ map<bool, sfixed32> field_map_bool_sfixed32_11 = 11;
+ map<bool, sfixed64> field_map_bool_sfixed64_12 = 12;
+ map<bool, sint32> field_map_bool_sint32_13 = 13;
+ map<bool, sint64> field_map_bool_sint64_14 = 14;
+ map<bool, string> field_map_bool_string_15 = 15;
+ map<bool, uint32> field_map_bool_uint32_16 = 16;
+ map<bool, uint64> field_map_bool_uint64_17 = 17;
+ map<fixed32, bool> field_map_fixed32_bool_18 = 18;
+ map<fixed32, bytes> field_map_fixed32_bytes_19 = 19;
+ map<fixed32, double> field_map_fixed32_double_20 = 20;
+ map<fixed32, Proto3Message.TestEnum> field_map_fixed32_enum_21 = 21;
+ map<fixed32, fixed32> field_map_fixed32_fixed32_22 = 22;
+ map<fixed32, fixed64> field_map_fixed32_fixed64_23 = 23;
+ map<fixed32, float> field_map_fixed32_float_24 = 24;
+ map<fixed32, int32> field_map_fixed32_int32_25 = 25;
+ map<fixed32, int64> field_map_fixed32_int64_26 = 26;
+ map<fixed32, Proto3Message> field_map_fixed32_message_27 = 27;
+ map<fixed32, sfixed32> field_map_fixed32_sfixed32_28 = 28;
+ map<fixed32, sfixed64> field_map_fixed32_sfixed64_29 = 29;
+ map<fixed32, sint32> field_map_fixed32_sint32_30 = 30;
+ map<fixed32, sint64> field_map_fixed32_sint64_31 = 31;
+ map<fixed32, string> field_map_fixed32_string_32 = 32;
+ map<fixed32, uint32> field_map_fixed32_uint32_33 = 33;
+ map<fixed32, uint64> field_map_fixed32_uint64_34 = 34;
+ map<fixed64, bool> field_map_fixed64_bool_35 = 35;
+ map<fixed64, bytes> field_map_fixed64_bytes_36 = 36;
+ map<fixed64, double> field_map_fixed64_double_37 = 37;
+ map<fixed64, Proto3Message.TestEnum> field_map_fixed64_enum_38 = 38;
+ map<fixed64, fixed32> field_map_fixed64_fixed32_39 = 39;
+ map<fixed64, fixed64> field_map_fixed64_fixed64_40 = 40;
+ map<fixed64, float> field_map_fixed64_float_41 = 41;
+ map<fixed64, int32> field_map_fixed64_int32_42 = 42;
+ map<fixed64, int64> field_map_fixed64_int64_43 = 43;
+ map<fixed64, Proto3Message> field_map_fixed64_message_44 = 44;
+ map<fixed64, sfixed32> field_map_fixed64_sfixed32_45 = 45;
+ map<fixed64, sfixed64> field_map_fixed64_sfixed64_46 = 46;
+ map<fixed64, sint32> field_map_fixed64_sint32_47 = 47;
+ map<fixed64, sint64> field_map_fixed64_sint64_48 = 48;
+ map<fixed64, string> field_map_fixed64_string_49 = 49;
+ map<fixed64, uint32> field_map_fixed64_uint32_50 = 50;
+ map<fixed64, uint64> field_map_fixed64_uint64_51 = 51;
+ map<int32, bool> field_map_int32_bool_52 = 52;
+ map<int32, bytes> field_map_int32_bytes_53 = 53;
+ map<int32, double> field_map_int32_double_54 = 54;
+ map<int32, Proto3Message.TestEnum> field_map_int32_enum_55 = 55;
+ map<int32, fixed32> field_map_int32_fixed32_56 = 56;
+ map<int32, fixed64> field_map_int32_fixed64_57 = 57;
+ map<int32, float> field_map_int32_float_58 = 58;
+ map<int32, int32> field_map_int32_int32_59 = 59;
+ map<int32, int64> field_map_int32_int64_60 = 60;
+ map<int32, Proto3Message> field_map_int32_message_61 = 61;
+ map<int32, sfixed32> field_map_int32_sfixed32_62 = 62;
+ map<int32, sfixed64> field_map_int32_sfixed64_63 = 63;
+ map<int32, sint32> field_map_int32_sint32_64 = 64;
+ map<int32, sint64> field_map_int32_sint64_65 = 65;
+ map<int32, string> field_map_int32_string_66 = 66;
+ map<int32, uint32> field_map_int32_uint32_67 = 67;
+ map<int32, uint64> field_map_int32_uint64_68 = 68;
+ map<int64, bool> field_map_int64_bool_69 = 69;
+ map<int64, bytes> field_map_int64_bytes_70 = 70;
+ map<int64, double> field_map_int64_double_71 = 71;
+ map<int64, Proto3Message.TestEnum> field_map_int64_enum_72 = 72;
+ map<int64, fixed32> field_map_int64_fixed32_73 = 73;
+ map<int64, fixed64> field_map_int64_fixed64_74 = 74;
+ map<int64, float> field_map_int64_float_75 = 75;
+ map<int64, int32> field_map_int64_int32_76 = 76;
+ map<int64, int64> field_map_int64_int64_77 = 77;
+ map<int64, Proto3Message> field_map_int64_message_78 = 78;
+ map<int64, sfixed32> field_map_int64_sfixed32_79 = 79;
+ map<int64, sfixed64> field_map_int64_sfixed64_80 = 80;
+ map<int64, sint32> field_map_int64_sint32_81 = 81;
+ map<int64, sint64> field_map_int64_sint64_82 = 82;
+ map<int64, string> field_map_int64_string_83 = 83;
+ map<int64, uint32> field_map_int64_uint32_84 = 84;
+ map<int64, uint64> field_map_int64_uint64_85 = 85;
+ map<sfixed32, bool> field_map_sfixed32_bool_86 = 86;
+ map<sfixed32, bytes> field_map_sfixed32_bytes_87 = 87;
+ map<sfixed32, double> field_map_sfixed32_double_88 = 88;
+ map<sfixed32, Proto3Message.TestEnum> field_map_sfixed32_enum_89 = 89;
+ map<sfixed32, fixed32> field_map_sfixed32_fixed32_90 = 90;
+ map<sfixed32, fixed64> field_map_sfixed32_fixed64_91 = 91;
+ map<sfixed32, float> field_map_sfixed32_float_92 = 92;
+ map<sfixed32, int32> field_map_sfixed32_int32_93 = 93;
+ map<sfixed32, int64> field_map_sfixed32_int64_94 = 94;
+ map<sfixed32, Proto3Message> field_map_sfixed32_message_95 = 95;
+ map<sfixed32, sfixed32> field_map_sfixed32_sfixed32_96 = 96;
+ map<sfixed32, sfixed64> field_map_sfixed32_sfixed64_97 = 97;
+ map<sfixed32, sint32> field_map_sfixed32_sint32_98 = 98;
+ map<sfixed32, sint64> field_map_sfixed32_sint64_99 = 99;
+ map<sfixed32, string> field_map_sfixed32_string_100 = 100;
+ map<sfixed32, uint32> field_map_sfixed32_uint32_101 = 101;
+ map<sfixed32, uint64> field_map_sfixed32_uint64_102 = 102;
+ map<sfixed64, bool> field_map_sfixed64_bool_103 = 103;
+ map<sfixed64, bytes> field_map_sfixed64_bytes_104 = 104;
+ map<sfixed64, double> field_map_sfixed64_double_105 = 105;
+ map<sfixed64, Proto3Message.TestEnum> field_map_sfixed64_enum_106 = 106;
+ map<sfixed64, fixed32> field_map_sfixed64_fixed32_107 = 107;
+ map<sfixed64, fixed64> field_map_sfixed64_fixed64_108 = 108;
+ map<sfixed64, float> field_map_sfixed64_float_109 = 109;
+ map<sfixed64, int32> field_map_sfixed64_int32_110 = 110;
+ map<sfixed64, int64> field_map_sfixed64_int64_111 = 111;
+ map<sfixed64, Proto3Message> field_map_sfixed64_message_112 = 112;
+ map<sfixed64, sfixed32> field_map_sfixed64_sfixed32_113 = 113;
+ map<sfixed64, sfixed64> field_map_sfixed64_sfixed64_114 = 114;
+ map<sfixed64, sint32> field_map_sfixed64_sint32_115 = 115;
+ map<sfixed64, sint64> field_map_sfixed64_sint64_116 = 116;
+ map<sfixed64, string> field_map_sfixed64_string_117 = 117;
+ map<sfixed64, uint32> field_map_sfixed64_uint32_118 = 118;
+ map<sfixed64, uint64> field_map_sfixed64_uint64_119 = 119;
+ map<sint32, bool> field_map_sint32_bool_120 = 120;
+ map<sint32, bytes> field_map_sint32_bytes_121 = 121;
+ map<sint32, double> field_map_sint32_double_122 = 122;
+ map<sint32, Proto3Message.TestEnum> field_map_sint32_enum_123 = 123;
+ map<sint32, fixed32> field_map_sint32_fixed32_124 = 124;
+ map<sint32, fixed64> field_map_sint32_fixed64_125 = 125;
+ map<sint32, float> field_map_sint32_float_126 = 126;
+ map<sint32, int32> field_map_sint32_int32_127 = 127;
+ map<sint32, int64> field_map_sint32_int64_128 = 128;
+ map<sint32, Proto3Message> field_map_sint32_message_129 = 129;
+ map<sint32, sfixed32> field_map_sint32_sfixed32_130 = 130;
+ map<sint32, sfixed64> field_map_sint32_sfixed64_131 = 131;
+ map<sint32, sint32> field_map_sint32_sint32_132 = 132;
+ map<sint32, sint64> field_map_sint32_sint64_133 = 133;
+ map<sint32, string> field_map_sint32_string_134 = 134;
+ map<sint32, uint32> field_map_sint32_uint32_135 = 135;
+ map<sint32, uint64> field_map_sint32_uint64_136 = 136;
+ map<sint64, bool> field_map_sint64_bool_137 = 137;
+ map<sint64, bytes> field_map_sint64_bytes_138 = 138;
+ map<sint64, double> field_map_sint64_double_139 = 139;
+ map<sint64, Proto3Message.TestEnum> field_map_sint64_enum_140 = 140;
+ map<sint64, fixed32> field_map_sint64_fixed32_141 = 141;
+ map<sint64, fixed64> field_map_sint64_fixed64_142 = 142;
+ map<sint64, float> field_map_sint64_float_143 = 143;
+ map<sint64, int32> field_map_sint64_int32_144 = 144;
+ map<sint64, int64> field_map_sint64_int64_145 = 145;
+ map<sint64, Proto3Message> field_map_sint64_message_146 = 146;
+ map<sint64, sfixed32> field_map_sint64_sfixed32_147 = 147;
+ map<sint64, sfixed64> field_map_sint64_sfixed64_148 = 148;
+ map<sint64, sint32> field_map_sint64_sint32_149 = 149;
+ map<sint64, sint64> field_map_sint64_sint64_150 = 150;
+ map<sint64, string> field_map_sint64_string_151 = 151;
+ map<sint64, uint32> field_map_sint64_uint32_152 = 152;
+ map<sint64, uint64> field_map_sint64_uint64_153 = 153;
+ map<string, bool> field_map_string_bool_154 = 154;
+ map<string, bytes> field_map_string_bytes_155 = 155;
+ map<string, double> field_map_string_double_156 = 156;
+ map<string, Proto3Message.TestEnum> field_map_string_enum_157 = 157;
+ map<string, fixed32> field_map_string_fixed32_158 = 158;
+ map<string, fixed64> field_map_string_fixed64_159 = 159;
+ map<string, float> field_map_string_float_160 = 160;
+ map<string, int32> field_map_string_int32_161 = 161;
+ map<string, int64> field_map_string_int64_162 = 162;
+ map<string, Proto3Message> field_map_string_message_163 = 163;
+ map<string, sfixed32> field_map_string_sfixed32_164 = 164;
+ map<string, sfixed64> field_map_string_sfixed64_165 = 165;
+ map<string, sint32> field_map_string_sint32_166 = 166;
+ map<string, sint64> field_map_string_sint64_167 = 167;
+ map<string, string> field_map_string_string_168 = 168;
+ map<string, uint32> field_map_string_uint32_169 = 169;
+ map<string, uint64> field_map_string_uint64_170 = 170;
+ map<uint32, bool> field_map_uint32_bool_171 = 171;
+ map<uint32, bytes> field_map_uint32_bytes_172 = 172;
+ map<uint32, double> field_map_uint32_double_173 = 173;
+ map<uint32, Proto3Message.TestEnum> field_map_uint32_enum_174 = 174;
+ map<uint32, fixed32> field_map_uint32_fixed32_175 = 175;
+ map<uint32, fixed64> field_map_uint32_fixed64_176 = 176;
+ map<uint32, float> field_map_uint32_float_177 = 177;
+ map<uint32, int32> field_map_uint32_int32_178 = 178;
+ map<uint32, int64> field_map_uint32_int64_179 = 179;
+ map<uint32, Proto3Message> field_map_uint32_message_180 = 180;
+ map<uint32, sfixed32> field_map_uint32_sfixed32_181 = 181;
+ map<uint32, sfixed64> field_map_uint32_sfixed64_182 = 182;
+ map<uint32, sint32> field_map_uint32_sint32_183 = 183;
+ map<uint32, sint64> field_map_uint32_sint64_184 = 184;
+ map<uint32, string> field_map_uint32_string_185 = 185;
+ map<uint32, uint32> field_map_uint32_uint32_186 = 186;
+ map<uint32, uint64> field_map_uint32_uint64_187 = 187;
+ map<uint64, bool> field_map_uint64_bool_188 = 188;
+ map<uint64, bytes> field_map_uint64_bytes_189 = 189;
+ map<uint64, double> field_map_uint64_double_190 = 190;
+ map<uint64, Proto3Message.TestEnum> field_map_uint64_enum_191 = 191;
+ map<uint64, fixed32> field_map_uint64_fixed32_192 = 192;
+ map<uint64, fixed64> field_map_uint64_fixed64_193 = 193;
+ map<uint64, float> field_map_uint64_float_194 = 194;
+ map<uint64, int32> field_map_uint64_int32_195 = 195;
+ map<uint64, int64> field_map_uint64_int64_196 = 196;
+ map<uint64, Proto3Message> field_map_uint64_message_197 = 197;
+ map<uint64, sfixed32> field_map_uint64_sfixed32_198 = 198;
+ map<uint64, sfixed64> field_map_uint64_sfixed64_199 = 199;
+ map<uint64, sint32> field_map_uint64_sint32_200 = 200;
+ map<uint64, sint64> field_map_uint64_sint64_201 = 201;
+ map<uint64, string> field_map_uint64_string_202 = 202;
+ map<uint64, uint32> field_map_uint64_uint32_203 = 203;
+ map<uint64, uint64> field_map_uint64_uint64_204 = 204;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto b/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto
new file mode 100755
index 000000000..ed364ec9f
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto
@@ -0,0 +1,319 @@
+// 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";
+
+option java_package = "com.google.protobuf.testing";
+option java_outer_classname = "Proto3TestingLite";
+package protobuf.experimental;
+
+message Proto3MessageLite {
+ enum TestEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ }
+
+ double field_double_1 = 1;
+ float field_float_2 = 2;
+ int64 field_int64_3 = 3;
+ uint64 field_uint64_4 = 4;
+ int32 field_int32_5 = 5;
+ fixed64 field_fixed64_6 = 6;
+ fixed32 field_fixed32_7 = 7;
+ bool field_bool_8 = 8;
+ string field_string_9 = 9;
+ Proto3MessageLite field_message_10 = 10;
+ bytes field_bytes_11 = 11;
+ uint32 field_uint32_12 = 12;
+ TestEnum field_enum_13 = 13;
+ sfixed32 field_sfixed32_14 = 14;
+ sfixed64 field_sfixed64_15 = 15;
+ sint32 field_sint32_16 = 16;
+ sint64 field_sint64_17 = 17;
+ repeated double field_double_list_18 = 18 [packed = false];
+ repeated float field_float_list_19 = 19 [packed = false];
+ repeated int64 field_int64_list_20 = 20 [packed = false];
+ repeated uint64 field_uint64_list_21 = 21 [packed = false];
+ repeated int32 field_int32_list_22 = 22 [packed = false];
+ repeated fixed64 field_fixed64_list_23 = 23 [packed = false];
+ repeated fixed32 field_fixed32_list_24 = 24 [packed = false];
+ repeated bool field_bool_list_25 = 25 [packed = false];
+ repeated string field_string_list_26 = 26 [packed = false];
+ repeated Proto3MessageLite field_message_list_27 = 27 [packed = false];
+ repeated bytes field_bytes_list_28 = 28 [packed = false];
+ repeated uint32 field_uint32_list_29 = 29 [packed = false];
+ repeated TestEnum field_enum_list_30 = 30 [packed = false];
+ repeated sfixed32 field_sfixed32_list_31 = 31 [packed = false];
+ repeated sfixed64 field_sfixed64_list_32 = 32 [packed = false];
+ repeated sint32 field_sint32_list_33 = 33 [packed = false];
+ repeated sint64 field_sint64_list_34 = 34 [packed = false];
+ repeated double field_double_list_packed_35 = 35 [packed = true];
+ repeated float field_float_list_packed_36 = 36 [packed = true];
+ repeated int64 field_int64_list_packed_37 = 37 [packed = true];
+ repeated uint64 field_uint64_list_packed_38 = 38 [packed = true];
+ repeated int32 field_int32_list_packed_39 = 39 [packed = true];
+ repeated fixed64 field_fixed64_list_packed_40 = 40 [packed = true];
+ repeated fixed32 field_fixed32_list_packed_41 = 41 [packed = true];
+ repeated bool field_bool_list_packed_42 = 42 [packed = true];
+ repeated uint32 field_uint32_list_packed_43 = 43 [packed = true];
+ repeated TestEnum field_enum_list_packed_44 = 44 [packed = true];
+ repeated sfixed32 field_sfixed32_list_packed_45 = 45 [packed = true];
+ repeated sfixed64 field_sfixed64_list_packed_46 = 46 [packed = true];
+ repeated sint32 field_sint32_list_packed_47 = 47 [packed = true];
+ repeated sint64 field_sint64_list_packed_48 = 48 [packed = true];
+ oneof test_oneof {
+ double field_double_53 = 53;
+ float field_float_54 = 54;
+ int64 field_int64_55 = 55;
+ uint64 field_uint64_56 = 56;
+ int32 field_int32_57 = 57;
+ fixed64 field_fixed64_58 = 58;
+ fixed32 field_fixed32_59 = 59;
+ bool field_bool_60 = 60;
+ string field_string_61 = 61;
+ Proto3MessageLite field_message_62 = 62;
+ bytes field_bytes_63 = 63;
+ uint32 field_uint32_64 = 64;
+ sfixed32 field_sfixed32_65 = 65;
+ sfixed64 field_sfixed64_66 = 66;
+ sint32 field_sint32_67 = 67;
+ sint64 field_sint64_68 = 68;
+ }
+}
+
+message Proto3EmptyLite {}
+
+message Proto3MessageLiteWithMaps {
+ map<bool, bool> field_map_bool_bool_1 = 1;
+ map<bool, bytes> field_map_bool_bytes_2 = 2;
+ map<bool, double> field_map_bool_double_3 = 3;
+ map<bool, Proto3MessageLite.TestEnum> field_map_bool_enum_4 = 4;
+ map<bool, fixed32> field_map_bool_fixed32_5 = 5;
+ map<bool, fixed64> field_map_bool_fixed64_6 = 6;
+ map<bool, float> field_map_bool_float_7 = 7;
+ map<bool, int32> field_map_bool_int32_8 = 8;
+ map<bool, int64> field_map_bool_int64_9 = 9;
+ map<bool, Proto3MessageLite> field_map_bool_message_10 = 10;
+ map<bool, sfixed32> field_map_bool_sfixed32_11 = 11;
+ map<bool, sfixed64> field_map_bool_sfixed64_12 = 12;
+ map<bool, sint32> field_map_bool_sint32_13 = 13;
+ map<bool, sint64> field_map_bool_sint64_14 = 14;
+ map<bool, string> field_map_bool_string_15 = 15;
+ map<bool, uint32> field_map_bool_uint32_16 = 16;
+ map<bool, uint64> field_map_bool_uint64_17 = 17;
+ map<fixed32, bool> field_map_fixed32_bool_18 = 18;
+ map<fixed32, bytes> field_map_fixed32_bytes_19 = 19;
+ map<fixed32, double> field_map_fixed32_double_20 = 20;
+ map<fixed32, Proto3MessageLite.TestEnum> field_map_fixed32_enum_21 = 21;
+ map<fixed32, fixed32> field_map_fixed32_fixed32_22 = 22;
+ map<fixed32, fixed64> field_map_fixed32_fixed64_23 = 23;
+ map<fixed32, float> field_map_fixed32_float_24 = 24;
+ map<fixed32, int32> field_map_fixed32_int32_25 = 25;
+ map<fixed32, int64> field_map_fixed32_int64_26 = 26;
+ map<fixed32, Proto3MessageLite> field_map_fixed32_message_27 = 27;
+ map<fixed32, sfixed32> field_map_fixed32_sfixed32_28 = 28;
+ map<fixed32, sfixed64> field_map_fixed32_sfixed64_29 = 29;
+ map<fixed32, sint32> field_map_fixed32_sint32_30 = 30;
+ map<fixed32, sint64> field_map_fixed32_sint64_31 = 31;
+ map<fixed32, string> field_map_fixed32_string_32 = 32;
+ map<fixed32, uint32> field_map_fixed32_uint32_33 = 33;
+ map<fixed32, uint64> field_map_fixed32_uint64_34 = 34;
+ map<fixed64, bool> field_map_fixed64_bool_35 = 35;
+ map<fixed64, bytes> field_map_fixed64_bytes_36 = 36;
+ map<fixed64, double> field_map_fixed64_double_37 = 37;
+ map<fixed64, Proto3MessageLite.TestEnum> field_map_fixed64_enum_38 = 38;
+ map<fixed64, fixed32> field_map_fixed64_fixed32_39 = 39;
+ map<fixed64, fixed64> field_map_fixed64_fixed64_40 = 40;
+ map<fixed64, float> field_map_fixed64_float_41 = 41;
+ map<fixed64, int32> field_map_fixed64_int32_42 = 42;
+ map<fixed64, int64> field_map_fixed64_int64_43 = 43;
+ map<fixed64, Proto3MessageLite> field_map_fixed64_message_44 = 44;
+ map<fixed64, sfixed32> field_map_fixed64_sfixed32_45 = 45;
+ map<fixed64, sfixed64> field_map_fixed64_sfixed64_46 = 46;
+ map<fixed64, sint32> field_map_fixed64_sint32_47 = 47;
+ map<fixed64, sint64> field_map_fixed64_sint64_48 = 48;
+ map<fixed64, string> field_map_fixed64_string_49 = 49;
+ map<fixed64, uint32> field_map_fixed64_uint32_50 = 50;
+ map<fixed64, uint64> field_map_fixed64_uint64_51 = 51;
+ map<int32, bool> field_map_int32_bool_52 = 52;
+ map<int32, bytes> field_map_int32_bytes_53 = 53;
+ map<int32, double> field_map_int32_double_54 = 54;
+ map<int32, Proto3MessageLite.TestEnum> field_map_int32_enum_55 = 55;
+ map<int32, fixed32> field_map_int32_fixed32_56 = 56;
+ map<int32, fixed64> field_map_int32_fixed64_57 = 57;
+ map<int32, float> field_map_int32_float_58 = 58;
+ map<int32, int32> field_map_int32_int32_59 = 59;
+ map<int32, int64> field_map_int32_int64_60 = 60;
+ map<int32, Proto3MessageLite> field_map_int32_message_61 = 61;
+ map<int32, sfixed32> field_map_int32_sfixed32_62 = 62;
+ map<int32, sfixed64> field_map_int32_sfixed64_63 = 63;
+ map<int32, sint32> field_map_int32_sint32_64 = 64;
+ map<int32, sint64> field_map_int32_sint64_65 = 65;
+ map<int32, string> field_map_int32_string_66 = 66;
+ map<int32, uint32> field_map_int32_uint32_67 = 67;
+ map<int32, uint64> field_map_int32_uint64_68 = 68;
+ map<int64, bool> field_map_int64_bool_69 = 69;
+ map<int64, bytes> field_map_int64_bytes_70 = 70;
+ map<int64, double> field_map_int64_double_71 = 71;
+ map<int64, Proto3MessageLite.TestEnum> field_map_int64_enum_72 = 72;
+ map<int64, fixed32> field_map_int64_fixed32_73 = 73;
+ map<int64, fixed64> field_map_int64_fixed64_74 = 74;
+ map<int64, float> field_map_int64_float_75 = 75;
+ map<int64, int32> field_map_int64_int32_76 = 76;
+ map<int64, int64> field_map_int64_int64_77 = 77;
+ map<int64, Proto3MessageLite> field_map_int64_message_78 = 78;
+ map<int64, sfixed32> field_map_int64_sfixed32_79 = 79;
+ map<int64, sfixed64> field_map_int64_sfixed64_80 = 80;
+ map<int64, sint32> field_map_int64_sint32_81 = 81;
+ map<int64, sint64> field_map_int64_sint64_82 = 82;
+ map<int64, string> field_map_int64_string_83 = 83;
+ map<int64, uint32> field_map_int64_uint32_84 = 84;
+ map<int64, uint64> field_map_int64_uint64_85 = 85;
+ map<sfixed32, bool> field_map_sfixed32_bool_86 = 86;
+ map<sfixed32, bytes> field_map_sfixed32_bytes_87 = 87;
+ map<sfixed32, double> field_map_sfixed32_double_88 = 88;
+ map<sfixed32, Proto3MessageLite.TestEnum> field_map_sfixed32_enum_89 = 89;
+ map<sfixed32, fixed32> field_map_sfixed32_fixed32_90 = 90;
+ map<sfixed32, fixed64> field_map_sfixed32_fixed64_91 = 91;
+ map<sfixed32, float> field_map_sfixed32_float_92 = 92;
+ map<sfixed32, int32> field_map_sfixed32_int32_93 = 93;
+ map<sfixed32, int64> field_map_sfixed32_int64_94 = 94;
+ map<sfixed32, Proto3MessageLite> field_map_sfixed32_message_95 = 95;
+ map<sfixed32, sfixed32> field_map_sfixed32_sfixed32_96 = 96;
+ map<sfixed32, sfixed64> field_map_sfixed32_sfixed64_97 = 97;
+ map<sfixed32, sint32> field_map_sfixed32_sint32_98 = 98;
+ map<sfixed32, sint64> field_map_sfixed32_sint64_99 = 99;
+ map<sfixed32, string> field_map_sfixed32_string_100 = 100;
+ map<sfixed32, uint32> field_map_sfixed32_uint32_101 = 101;
+ map<sfixed32, uint64> field_map_sfixed32_uint64_102 = 102;
+ map<sfixed64, bool> field_map_sfixed64_bool_103 = 103;
+ map<sfixed64, bytes> field_map_sfixed64_bytes_104 = 104;
+ map<sfixed64, double> field_map_sfixed64_double_105 = 105;
+ map<sfixed64, Proto3MessageLite.TestEnum> field_map_sfixed64_enum_106 = 106;
+ map<sfixed64, fixed32> field_map_sfixed64_fixed32_107 = 107;
+ map<sfixed64, fixed64> field_map_sfixed64_fixed64_108 = 108;
+ map<sfixed64, float> field_map_sfixed64_float_109 = 109;
+ map<sfixed64, int32> field_map_sfixed64_int32_110 = 110;
+ map<sfixed64, int64> field_map_sfixed64_int64_111 = 111;
+ map<sfixed64, Proto3MessageLite> field_map_sfixed64_message_112 = 112;
+ map<sfixed64, sfixed32> field_map_sfixed64_sfixed32_113 = 113;
+ map<sfixed64, sfixed64> field_map_sfixed64_sfixed64_114 = 114;
+ map<sfixed64, sint32> field_map_sfixed64_sint32_115 = 115;
+ map<sfixed64, sint64> field_map_sfixed64_sint64_116 = 116;
+ map<sfixed64, string> field_map_sfixed64_string_117 = 117;
+ map<sfixed64, uint32> field_map_sfixed64_uint32_118 = 118;
+ map<sfixed64, uint64> field_map_sfixed64_uint64_119 = 119;
+ map<sint32, bool> field_map_sint32_bool_120 = 120;
+ map<sint32, bytes> field_map_sint32_bytes_121 = 121;
+ map<sint32, double> field_map_sint32_double_122 = 122;
+ map<sint32, Proto3MessageLite.TestEnum> field_map_sint32_enum_123 = 123;
+ map<sint32, fixed32> field_map_sint32_fixed32_124 = 124;
+ map<sint32, fixed64> field_map_sint32_fixed64_125 = 125;
+ map<sint32, float> field_map_sint32_float_126 = 126;
+ map<sint32, int32> field_map_sint32_int32_127 = 127;
+ map<sint32, int64> field_map_sint32_int64_128 = 128;
+ map<sint32, Proto3MessageLite> field_map_sint32_message_129 = 129;
+ map<sint32, sfixed32> field_map_sint32_sfixed32_130 = 130;
+ map<sint32, sfixed64> field_map_sint32_sfixed64_131 = 131;
+ map<sint32, sint32> field_map_sint32_sint32_132 = 132;
+ map<sint32, sint64> field_map_sint32_sint64_133 = 133;
+ map<sint32, string> field_map_sint32_string_134 = 134;
+ map<sint32, uint32> field_map_sint32_uint32_135 = 135;
+ map<sint32, uint64> field_map_sint32_uint64_136 = 136;
+ map<sint64, bool> field_map_sint64_bool_137 = 137;
+ map<sint64, bytes> field_map_sint64_bytes_138 = 138;
+ map<sint64, double> field_map_sint64_double_139 = 139;
+ map<sint64, Proto3MessageLite.TestEnum> field_map_sint64_enum_140 = 140;
+ map<sint64, fixed32> field_map_sint64_fixed32_141 = 141;
+ map<sint64, fixed64> field_map_sint64_fixed64_142 = 142;
+ map<sint64, float> field_map_sint64_float_143 = 143;
+ map<sint64, int32> field_map_sint64_int32_144 = 144;
+ map<sint64, int64> field_map_sint64_int64_145 = 145;
+ map<sint64, Proto3MessageLite> field_map_sint64_message_146 = 146;
+ map<sint64, sfixed32> field_map_sint64_sfixed32_147 = 147;
+ map<sint64, sfixed64> field_map_sint64_sfixed64_148 = 148;
+ map<sint64, sint32> field_map_sint64_sint32_149 = 149;
+ map<sint64, sint64> field_map_sint64_sint64_150 = 150;
+ map<sint64, string> field_map_sint64_string_151 = 151;
+ map<sint64, uint32> field_map_sint64_uint32_152 = 152;
+ map<sint64, uint64> field_map_sint64_uint64_153 = 153;
+ map<string, bool> field_map_string_bool_154 = 154;
+ map<string, bytes> field_map_string_bytes_155 = 155;
+ map<string, double> field_map_string_double_156 = 156;
+ map<string, Proto3MessageLite.TestEnum> field_map_string_enum_157 = 157;
+ map<string, fixed32> field_map_string_fixed32_158 = 158;
+ map<string, fixed64> field_map_string_fixed64_159 = 159;
+ map<string, float> field_map_string_float_160 = 160;
+ map<string, int32> field_map_string_int32_161 = 161;
+ map<string, int64> field_map_string_int64_162 = 162;
+ map<string, Proto3MessageLite> field_map_string_message_163 = 163;
+ map<string, sfixed32> field_map_string_sfixed32_164 = 164;
+ map<string, sfixed64> field_map_string_sfixed64_165 = 165;
+ map<string, sint32> field_map_string_sint32_166 = 166;
+ map<string, sint64> field_map_string_sint64_167 = 167;
+ map<string, string> field_map_string_string_168 = 168;
+ map<string, uint32> field_map_string_uint32_169 = 169;
+ map<string, uint64> field_map_string_uint64_170 = 170;
+ map<uint32, bool> field_map_uint32_bool_171 = 171;
+ map<uint32, bytes> field_map_uint32_bytes_172 = 172;
+ map<uint32, double> field_map_uint32_double_173 = 173;
+ map<uint32, Proto3MessageLite.TestEnum> field_map_uint32_enum_174 = 174;
+ map<uint32, fixed32> field_map_uint32_fixed32_175 = 175;
+ map<uint32, fixed64> field_map_uint32_fixed64_176 = 176;
+ map<uint32, float> field_map_uint32_float_177 = 177;
+ map<uint32, int32> field_map_uint32_int32_178 = 178;
+ map<uint32, int64> field_map_uint32_int64_179 = 179;
+ map<uint32, Proto3MessageLite> field_map_uint32_message_180 = 180;
+ map<uint32, sfixed32> field_map_uint32_sfixed32_181 = 181;
+ map<uint32, sfixed64> field_map_uint32_sfixed64_182 = 182;
+ map<uint32, sint32> field_map_uint32_sint32_183 = 183;
+ map<uint32, sint64> field_map_uint32_sint64_184 = 184;
+ map<uint32, string> field_map_uint32_string_185 = 185;
+ map<uint32, uint32> field_map_uint32_uint32_186 = 186;
+ map<uint32, uint64> field_map_uint32_uint64_187 = 187;
+ map<uint64, bool> field_map_uint64_bool_188 = 188;
+ map<uint64, bytes> field_map_uint64_bytes_189 = 189;
+ map<uint64, double> field_map_uint64_double_190 = 190;
+ map<uint64, Proto3MessageLite.TestEnum> field_map_uint64_enum_191 = 191;
+ map<uint64, fixed32> field_map_uint64_fixed32_192 = 192;
+ map<uint64, fixed64> field_map_uint64_fixed64_193 = 193;
+ map<uint64, float> field_map_uint64_float_194 = 194;
+ map<uint64, int32> field_map_uint64_int32_195 = 195;
+ map<uint64, int64> field_map_uint64_int64_196 = 196;
+ map<uint64, Proto3MessageLite> field_map_uint64_message_197 = 197;
+ map<uint64, sfixed32> field_map_uint64_sfixed32_198 = 198;
+ map<uint64, sfixed64> field_map_uint64_sfixed64_199 = 199;
+ map<uint64, sint32> field_map_uint64_sint32_200 = 200;
+ map<uint64, sint64> field_map_uint64_sint64_201 = 201;
+ map<uint64, string> field_map_uint64_string_202 = 202;
+ map<uint64, uint32> field_map_uint64_uint32_203 = 203;
+ map<uint64, uint64> field_map_uint64_uint64_204 = 204;
+}
diff --git a/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto b/java/core/src/test/proto/com/google/protobuf/wrappers_test.proto
new file mode 100755
index 000000000..f151edf8e
--- /dev/null
+++ b/java/core/src/test/proto/com/google/protobuf/wrappers_test.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.
+
+syntax = "proto3";
+
+package wrappers_test;
+option java_package = "com.google.protobuf.wrapperstest";
+option java_outer_classname = "WrappersTestProto";
+import "google/protobuf/wrappers.proto";
+
+message TopLevelMessage {
+ int32 field1 = 1;
+ .google.protobuf.DoubleValue field_double = 2;
+ .google.protobuf.FloatValue field_float = 3;
+ .google.protobuf.Int64Value field_int64 = 4;
+ .google.protobuf.UInt64Value field_uint64 = 5;
+ .google.protobuf.Int32Value field_int32 = 6;
+ .google.protobuf.UInt32Value field_uint32 = 7;
+ .google.protobuf.BoolValue field_bool = 8;
+ .google.protobuf.StringValue field_string = 9;
+ .google.protobuf.BytesValue field_bytes = 10;
+}
diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
index 89213a76c..960b2037c 100644..100755
--- a/java/core/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -50,6 +50,8 @@ import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite;
import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
import map_lite_test.MapTestProto.TestMap;
import map_lite_test.MapTestProto.TestMap.MessageValue;
+import protobuf_unittest.NestedExtensionLite;
+import protobuf_unittest.NonNestedExtensionLite;
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;
@@ -2338,6 +2340,26 @@ public class LiteTest extends TestCase {
}
}
+ public void testExtensionRenamesKeywords() {
+ assertTrue(NonNestedExtensionLite.package_ instanceof GeneratedMessageLite.GeneratedExtension);
+ assertTrue(
+ NestedExtensionLite.MyNestedExtensionLite.private_
+ instanceof GeneratedMessageLite.GeneratedExtension);
+
+ NonNestedExtensionLite.MessageLiteToBeExtended msg =
+ NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder()
+ .setExtension(NonNestedExtensionLite.package_, true)
+ .build();
+ assertTrue(msg.getExtension(NonNestedExtensionLite.package_));
+
+ msg =
+ NonNestedExtensionLite.MessageLiteToBeExtended.newBuilder()
+ .setExtension(NestedExtensionLite.MyNestedExtensionLite.private_, 2.4)
+ .build();
+ assertEquals(
+ 2.4, msg.getExtension(NestedExtensionLite.MyNestedExtensionLite.private_), 0.001);
+ }
+
private static final class OneTimeIterableList<T> extends ArrayList<T> {
private boolean wasIterated = false;
diff --git a/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java
new file mode 100755
index 000000000..4a1d89b93
--- /dev/null
+++ b/java/lite/src/test/java/com/google/protobuf/Proto2MessageLiteInfoFactory.java
@@ -0,0 +1,1327 @@
+// 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.FieldInfo.forField;
+import static com.google.protobuf.FieldInfo.forFieldWithEnumVerifier;
+import static com.google.protobuf.FieldInfo.forMapField;
+import static com.google.protobuf.FieldInfo.forOneofMemberField;
+import static com.google.protobuf.FieldInfo.forProto2OptionalField;
+import static com.google.protobuf.FieldInfo.forProto2RequiredField;
+import static com.google.protobuf.FieldInfo.forRepeatedMessageField;
+
+import com.google.protobuf.testing.Proto2TestingLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2EmptyLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroup49;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroup69;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldGroupList51;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.FieldRequiredGroup88;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.RequiredNestedMessage;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLite.TestEnum;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithExtensions;
+import com.google.protobuf.testing.Proto2TestingLite.Proto2MessageLiteWithMaps;
+import java.lang.reflect.Field;
+
+/** A factory that generates a hard-coded info for {@link Proto2MessageLite}. */
+public final class Proto2MessageLiteInfoFactory implements MessageInfoFactory {
+ private static final Proto2MessageLiteInfoFactory instanceForRawMessageInfo =
+ new Proto2MessageLiteInfoFactory(true);
+ private static final Proto2MessageLiteInfoFactory instanceForStructuralMessageInfo =
+ new Proto2MessageLiteInfoFactory(false);
+
+ public static Proto2MessageLiteInfoFactory getInstanceForRawMessageInfo() {
+ return instanceForRawMessageInfo;
+ }
+
+ public static Proto2MessageLiteInfoFactory getInstanceForStructuralMessageInfo() {
+ return instanceForStructuralMessageInfo;
+ }
+
+ private final boolean produceRawMessageInfo;
+
+ private Proto2MessageLiteInfoFactory(boolean produceRawMessageInfo) {
+ this.produceRawMessageInfo = produceRawMessageInfo;
+ }
+
+ @Override
+ public boolean isSupported(Class<?> clazz) {
+ return true;
+ }
+
+ @Override
+ public MessageInfo messageInfoFor(Class<?> clazz) {
+ return produceRawMessageInfo ? rawMessageInfoFor(clazz) : structuralMessageInfoFor(clazz);
+ }
+
+ private MessageInfo rawMessageInfoFor(Class<?> clazz) {
+ if (Proto2MessageLite.class.isAssignableFrom(clazz)) {
+ return newRawMessageInfoForProto2MessageLite();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ private MessageInfo newRawMessageInfoForProto2MessageLite() {
+ java.lang.Object[] objects =
+ new java.lang.Object[] {
+ "testOneof_",
+ "testOneofCase_",
+ "bitField0_",
+ "bitField1_",
+ "fieldDouble1_",
+ "fieldFloat2_",
+ "fieldInt643_",
+ "fieldUint644_",
+ "fieldInt325_",
+ "fieldFixed646_",
+ "fieldFixed327_",
+ "fieldBool8_",
+ "fieldString9_",
+ "fieldMessage10_",
+ "fieldBytes11_",
+ "fieldUint3212_",
+ "fieldEnum13_",
+ Proto2MessageLite.TestEnum.internalGetVerifier(),
+ "fieldSfixed3214_",
+ "fieldSfixed6415_",
+ "fieldSint3216_",
+ "fieldSint6417_",
+ "fieldDoubleList18_",
+ "fieldFloatList19_",
+ "fieldInt64List20_",
+ "fieldUint64List21_",
+ "fieldInt32List22_",
+ "fieldFixed64List23_",
+ "fieldFixed32List24_",
+ "fieldBoolList25_",
+ "fieldStringList26_",
+ "fieldMessageList27_",
+ Proto2MessageLite.class,
+ "fieldBytesList28_",
+ "fieldUint32List29_",
+ "fieldEnumList30_",
+ Proto2MessageLite.TestEnum.internalGetVerifier(),
+ "fieldSfixed32List31_",
+ "fieldSfixed64List32_",
+ "fieldSint32List33_",
+ "fieldSint64List34_",
+ "fieldDoubleListPacked35_",
+ "fieldFloatListPacked36_",
+ "fieldInt64ListPacked37_",
+ "fieldUint64ListPacked38_",
+ "fieldInt32ListPacked39_",
+ "fieldFixed64ListPacked40_",
+ "fieldFixed32ListPacked41_",
+ "fieldBoolListPacked42_",
+ "fieldUint32ListPacked43_",
+ "fieldEnumListPacked44_",
+ Proto2MessageLite.TestEnum.internalGetVerifier(),
+ "fieldSfixed32ListPacked45_",
+ "fieldSfixed64ListPacked46_",
+ "fieldSint32ListPacked47_",
+ "fieldSint64ListPacked48_",
+ "fieldGroup49_",
+ "fieldGroupList51_",
+ Proto2MessageLite.FieldGroupList51.class,
+ Proto2MessageLite.class,
+ Proto2MessageLite.FieldGroup69.class,
+ "fieldRequiredDouble71_",
+ "fieldRequiredFloat72_",
+ "fieldRequiredInt6473_",
+ "fieldRequiredUint6474_",
+ "fieldRequiredInt3275_",
+ "fieldRequiredFixed6476_",
+ "fieldRequiredFixed3277_",
+ "fieldRequiredBool78_",
+ "fieldRequiredString79_",
+ "fieldRequiredMessage80_",
+ "fieldRequiredBytes81_",
+ "fieldRequiredUint3282_",
+ "fieldRequiredEnum83_",
+ Proto2MessageLite.TestEnum.internalGetVerifier(),
+ "fieldRequiredSfixed3284_",
+ "fieldRequiredSfixed6485_",
+ "fieldRequiredSint3286_",
+ "fieldRequiredSint6487_",
+ "fieldRequiredGroup88_",
+ };
+ // To update this after a proto change, run protoc on proto2_message_lite.proto and copy over
+ // the content of the generated buildMessageInfo() method here.
+ java.lang.String info =
+ "\u0001U\u0001\u0002\u0001XU\u0000 \u0015\u0001\u0000\u0000\u0002\u0001\u0001\u0003"
+ + "\u0002\u0002\u0004\u0003\u0003\u0005\u0004\u0004\u0006\u0005\u0005\u0007\u0006\u0006"
+ + "\b\u0007\u0007\t\b\b\n\u0409\t\u000b\n\n\f\u000b\u000b\r\f\f\u000e\r\r\u000f\u000e"
+ + "\u000e\u0010\u000f\u000f\u0011\u0010\u0010\u0012\u0012\u0013\u0013\u0014\u0014\u0015"
+ + "\u0015\u0016\u0016\u0017\u0017\u0018\u0018\u0019\u0019\u001a\u001a\u001b\u041b\u001c"
+ + "\u001c\u001d\u001d\u001e\u001e\u001f\u001f !!\"\"##$$%%&&\'\'(())**++,,--..//00"
+ + "1\u0011\u00113153\u000064\u000075\u000086\u000097\u0000:8\u0000;9\u0000<:\u0000="
+ + ";\u0000>\u043c\u0000?=\u0000@>\u0000A@\u0000BA\u0000CB\u0000DC\u0000ED\u0000G\u0500"
+ + "#H\u0501$I\u0502%J\u0503&K\u0504\'L\u0505(M\u0506)N\u0507*O\u0508+P\u0509,Q\u050a"
+ + "-R\u050b.S\u050c/T\u050d0U\u050e1V\u050f2W\u05103X\u05114";
+ return new RawMessageInfo(Proto2MessageLite.getDefaultInstance(), info, objects);
+ }
+
+ private MessageInfo structuralMessageInfoFor(Class<?> clazz) {
+ if (Proto2MessageLite.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2MessageLite();
+ } else if (FieldGroup49.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroup49();
+ } else if (FieldGroupList51.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroupList51();
+ } else if (FieldGroup69.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldGroup69();
+ } else if (FieldRequiredGroup88.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForFieldRequiredGroup88();
+ } else if (RequiredNestedMessage.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForRequiredNestedMessage();
+ } else if (Proto2EmptyLite.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2EmptyLite();
+ } else if (Proto2MessageLiteWithExtensions.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2MessageLiteWithExtensions();
+ } else if (Proto2TestingLite.FieldGroup49.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForExtensionFieldGroup49();
+ } else if (Proto2TestingLite.FieldGroupList51.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForExtensionFieldGroupList51();
+ } else if (Proto2TestingLite.Proto2MessageLiteWithMaps.class.isAssignableFrom(clazz)) {
+ return newMessageInfoForProto2MessageLiteWithMaps();
+ } else {
+ throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
+ }
+ }
+
+ /**
+ * Creates a new hard-coded info for {@link Proto2MessageLite}. Each time this is called, we
+ * manually go through the entire process of what a message would do if it self-registered its own
+ * info, including looking up each field by name. This is done for benchmarking purposes, so that
+ * we get a more accurate representation of the time it takes to perform this process.
+ */
+ private static StructuralMessageInfo newMessageInfoForProto2MessageLite() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(48);
+ builder.withCheckInitialized(
+ new int[] {
+ 10, 27, 62, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
+ });
+ lookupFieldsByName(builder);
+ return builder.build();
+ }
+
+ private static void lookupFieldsByName(StructuralMessageInfo.Builder builder) {
+ Field bitField0 = field(Proto2MessageLite.class, "bitField0_");
+
+ builder.withDefaultInstance(Proto2MessageLite.getDefaultInstance());
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldDouble1_"),
+ 1,
+ FieldType.DOUBLE,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldFloat2_"),
+ 2,
+ FieldType.FLOAT,
+ bitField0,
+ 0x00000002,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldInt643_"),
+ 3,
+ FieldType.INT64,
+ bitField0,
+ 0x00000004,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldUint644_"),
+ 4,
+ FieldType.UINT64,
+ bitField0,
+ 0x00000008,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldInt325_"),
+ 5,
+ FieldType.INT32,
+ bitField0,
+ 0x00000010,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldFixed646_"),
+ 6,
+ FieldType.FIXED64,
+ bitField0,
+ 0x00000020,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldFixed327_"),
+ 7,
+ FieldType.FIXED32,
+ bitField0,
+ 0x00000040,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldBool8_"),
+ 8,
+ FieldType.BOOL,
+ bitField0,
+ 0x00000080,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldString9_"),
+ 9,
+ FieldType.STRING,
+ bitField0,
+ 0x00000100,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldMessage10_"),
+ 10,
+ FieldType.MESSAGE,
+ bitField0,
+ 0x00000200,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldBytes11_"),
+ 11,
+ FieldType.BYTES,
+ bitField0,
+ 0x00000400,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldUint3212_"),
+ 12,
+ FieldType.UINT32,
+ bitField0,
+ 0x00000800,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldEnum13_"),
+ 13,
+ FieldType.ENUM,
+ bitField0,
+ 0x00001000,
+ false,
+ TestEnum.internalGetVerifier()));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldSfixed3214_"),
+ 14,
+ FieldType.SFIXED32,
+ bitField0,
+ 0x00002000,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldSfixed6415_"),
+ 15,
+ FieldType.SFIXED64,
+ bitField0,
+ 0x00004000,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldSint3216_"),
+ 16,
+ FieldType.SINT32,
+ bitField0,
+ 0x00008000,
+ false,
+ null));
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldSint6417_"),
+ 17,
+ FieldType.SINT64,
+ bitField0,
+ 0x00010000,
+ false,
+ null));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldDoubleList18_"),
+ 18,
+ FieldType.DOUBLE_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFloatList19_"), 19, FieldType.FLOAT_LIST, false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldInt64List20_"), 20, FieldType.INT64_LIST, false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldUint64List21_"),
+ 21,
+ FieldType.UINT64_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldInt32List22_"), 22, FieldType.INT32_LIST, false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFixed64List23_"),
+ 23,
+ FieldType.FIXED64_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFixed32List24_"),
+ 24,
+ FieldType.FIXED32_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldBoolList25_"), 25, FieldType.BOOL_LIST, false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldStringList26_"),
+ 26,
+ FieldType.STRING_LIST,
+ false));
+ builder.withField(
+ forRepeatedMessageField(
+ field(Proto2MessageLite.class, "fieldMessageList27_"),
+ 27,
+ FieldType.MESSAGE_LIST,
+ Proto2MessageLite.class));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldBytesList28_"), 28, FieldType.BYTES_LIST, false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldUint32List29_"),
+ 29,
+ FieldType.UINT32_LIST,
+ false));
+ builder.withField(
+ forFieldWithEnumVerifier(
+ field(Proto2MessageLite.class, "fieldEnumList30_"),
+ 30,
+ FieldType.ENUM_LIST,
+ TestEnum.internalGetVerifier()));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSfixed32List31_"),
+ 31,
+ FieldType.SFIXED32_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSfixed64List32_"),
+ 32,
+ FieldType.SFIXED64_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSint32List33_"),
+ 33,
+ FieldType.SINT32_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSint64List34_"),
+ 34,
+ FieldType.SINT64_LIST,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldDoubleListPacked35_"),
+ 35,
+ FieldType.DOUBLE_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFloatListPacked36_"),
+ 36,
+ FieldType.FLOAT_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldInt64ListPacked37_"),
+ 37,
+ FieldType.INT64_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldUint64ListPacked38_"),
+ 38,
+ FieldType.UINT64_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldInt32ListPacked39_"),
+ 39,
+ FieldType.INT32_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFixed64ListPacked40_"),
+ 40,
+ FieldType.FIXED64_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldFixed32ListPacked41_"),
+ 41,
+ FieldType.FIXED32_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldBoolListPacked42_"),
+ 42,
+ FieldType.BOOL_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldUint32ListPacked43_"),
+ 43,
+ FieldType.UINT32_LIST_PACKED,
+ false));
+ builder.withField(
+ forFieldWithEnumVerifier(
+ field(Proto2MessageLite.class, "fieldEnumListPacked44_"),
+ 44,
+ FieldType.ENUM_LIST_PACKED,
+ TestEnum.internalGetVerifier()));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSfixed32ListPacked45_"),
+ 45,
+ FieldType.SFIXED32_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSfixed64ListPacked46_"),
+ 46,
+ FieldType.SFIXED64_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSint32ListPacked47_"),
+ 47,
+ FieldType.SINT32_LIST_PACKED,
+ false));
+ builder.withField(
+ forField(
+ field(Proto2MessageLite.class, "fieldSint64ListPacked48_"),
+ 48,
+ FieldType.SINT64_LIST_PACKED,
+ false));
+
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2MessageLite.class, "fieldGroup49_"),
+ 49,
+ FieldType.GROUP,
+ bitField0,
+ 0x00020000,
+ false,
+ null));
+ builder.withField(
+ forRepeatedMessageField(
+ field(Proto2MessageLite.class, "fieldGroupList51_"),
+ 51,
+ FieldType.GROUP_LIST,
+ Proto2MessageLite.FieldGroupList51.class));
+
+ OneofInfo oneof =
+ new OneofInfo(
+ 0,
+ field(Proto2MessageLite.class, "testOneofCase_"),
+ field(Proto2MessageLite.class, "testOneof_"));
+ builder.withField(forOneofMemberField(53, FieldType.DOUBLE, oneof, Double.class, false, null));
+ builder.withField(forOneofMemberField(54, FieldType.FLOAT, oneof, Float.class, false, null));
+ builder.withField(forOneofMemberField(55, FieldType.INT64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(56, FieldType.UINT64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(57, FieldType.INT32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(58, FieldType.FIXED64, oneof, Long.class, false, null));
+ builder.withField(
+ forOneofMemberField(59, FieldType.FIXED32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(60, FieldType.BOOL, oneof, Boolean.class, false, null));
+ builder.withField(forOneofMemberField(61, FieldType.STRING, oneof, String.class, false, null));
+ builder.withField(
+ forOneofMemberField(62, FieldType.MESSAGE, oneof, Proto2MessageLite.class, false, null));
+ builder.withField(
+ forOneofMemberField(63, FieldType.BYTES, oneof, ByteString.class, false, null));
+ builder.withField(forOneofMemberField(64, FieldType.UINT32, oneof, Integer.class, false, null));
+ builder.withField(
+ forOneofMemberField(65, FieldType.SFIXED32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(66, FieldType.SFIXED64, oneof, Long.class, false, null));
+ builder.withField(forOneofMemberField(67, FieldType.SINT32, oneof, Integer.class, false, null));
+ builder.withField(forOneofMemberField(68, FieldType.SINT64, oneof, Long.class, false, null));
+ builder.withField(
+ forOneofMemberField(
+ 69, FieldType.GROUP, oneof, Proto2MessageLite.FieldGroup69.class, false, null));
+
+ Field bitField1 = field(Proto2MessageLite.class, "bitField1_");
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredDouble71_"),
+ 71,
+ FieldType.DOUBLE,
+ bitField1,
+ 0x00000008,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredFloat72_"),
+ 72,
+ FieldType.FLOAT,
+ bitField1,
+ 0x00000010,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredInt6473_"),
+ 73,
+ FieldType.INT64,
+ bitField1,
+ 0x00000020,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredUint6474_"),
+ 74,
+ FieldType.UINT64,
+ bitField1,
+ 0x00000040,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredInt3275_"),
+ 75,
+ FieldType.INT32,
+ bitField1,
+ 0x00000080,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredFixed6476_"),
+ 76,
+ FieldType.FIXED64,
+ bitField1,
+ 0x00000100,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredFixed3277_"),
+ 77,
+ FieldType.FIXED32,
+ bitField1,
+ 0x00000200,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredBool78_"),
+ 78,
+ FieldType.BOOL,
+ bitField1,
+ 0x00000400,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredString79_"),
+ 79,
+ FieldType.STRING,
+ bitField1,
+ 0x00000800,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredMessage80_"),
+ 80,
+ FieldType.MESSAGE,
+ bitField1,
+ 0x00001000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredBytes81_"),
+ 81,
+ FieldType.BYTES,
+ bitField1,
+ 0x00002000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredUint3282_"),
+ 82,
+ FieldType.UINT32,
+ bitField1,
+ 0x00004000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredEnum83_"),
+ 83,
+ FieldType.ENUM,
+ bitField1,
+ 0x00008000,
+ false,
+ TestEnum.internalGetVerifier()));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredSfixed3284_"),
+ 84,
+ FieldType.SFIXED32,
+ bitField1,
+ 0x00010000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredSfixed6485_"),
+ 85,
+ FieldType.SFIXED64,
+ bitField1,
+ 0x00020000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredSint3286_"),
+ 86,
+ FieldType.SINT32,
+ bitField1,
+ 0x00040000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredSint6487_"),
+ 87,
+ FieldType.SINT64,
+ bitField1,
+ 0x00080000,
+ false,
+ null));
+ builder.withField(
+ forProto2RequiredField(
+ field(Proto2MessageLite.class, "fieldRequiredGroup88_"),
+ 88,
+ FieldType.GROUP,
+ bitField1,
+ 0x00100000,
+ false,
+ null));
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroup49() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroup49.class, "fieldInt3250_"),
+ 50,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroupList51() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroupList51.class, "fieldInt3252_"),
+ 52,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldGroup69() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldGroup69.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldGroup69.class, "fieldInt3270_"),
+ 70,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForRequiredNestedMessage() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(RequiredNestedMessage.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(RequiredNestedMessage.class, "value_"),
+ 1,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForFieldRequiredGroup88() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(FieldRequiredGroup88.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(FieldRequiredGroup88.class, "fieldInt3289_"),
+ 89,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto2EmptyLite() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForProto2MessageLiteWithExtensions() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(0);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForExtensionFieldGroup49() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(Proto2TestingLite.FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2TestingLite.FieldGroup49.class, "fieldInt3250_"),
+ 50,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+ private static StructuralMessageInfo newMessageInfoForExtensionFieldGroupList51() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder(1);
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ Field bitField0 = field(Proto2TestingLite.FieldGroup49.class, "bitField0_");
+ builder.withField(
+ forProto2OptionalField(
+ field(Proto2TestingLite.FieldGroupList51.class, "fieldInt3252_"),
+ 52,
+ FieldType.INT32,
+ bitField0,
+ 0x00000001,
+ false,
+ null));
+ return builder.build();
+ }
+
+
+ private static StructuralMessageInfo newMessageInfoForProto2MessageLiteWithMaps() {
+ StructuralMessageInfo.Builder builder = StructuralMessageInfo.newBuilder();
+ builder.withCheckInitialized(
+ new int[] {
+ 10, 27, 44, 61, 78, 95, 112, 129, 146, 163, 180, 197,
+ });
+ builder.withSyntax(ProtoSyntax.PROTO2);
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_bool_1", 1));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_bytes_2", 2));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_double_3", 3));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_enum_4", 4));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_fixed32_5", 5));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_fixed64_6", 6));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_float_7", 7));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_int32_8", 8));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_int64_9", 9));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_message_10", 10));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sfixed32_11", 11));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sfixed64_12", 12));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sint32_13", 13));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_sint64_14", 14));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_string_15", 15));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_uint32_16", 16));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_bool_uint64_17", 17));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_bool_18", 18));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_bytes_19", 19));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_double_20", 20));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_enum_21", 21));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_fixed32_22", 22));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_fixed64_23", 23));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_float_24", 24));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_int32_25", 25));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_int64_26", 26));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_message_27", 27));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sfixed32_28", 28));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sfixed64_29", 29));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sint32_30", 30));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_sint64_31", 31));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_string_32", 32));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_uint32_33", 33));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed32_uint64_34", 34));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_bool_35", 35));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_bytes_36", 36));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_double_37", 37));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_enum_38", 38));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_fixed32_39", 39));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_fixed64_40", 40));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_float_41", 41));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_int32_42", 42));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_int64_43", 43));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_message_44", 44));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sfixed32_45", 45));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sfixed64_46", 46));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sint32_47", 47));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_sint64_48", 48));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_string_49", 49));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_uint32_50", 50));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_fixed64_uint64_51", 51));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_bool_52", 52));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_bytes_53", 53));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_double_54", 54));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_enum_55", 55));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_fixed32_56", 56));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_fixed64_57", 57));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_float_58", 58));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_int32_59", 59));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_int64_60", 60));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_message_61", 61));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sfixed32_62", 62));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sfixed64_63", 63));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sint32_64", 64));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_sint64_65", 65));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_string_66", 66));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_uint32_67", 67));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int32_uint64_68", 68));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_bool_69", 69));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_bytes_70", 70));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_double_71", 71));
+ builder.withField(mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_enum_72", 72));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_fixed32_73", 73));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_fixed64_74", 74));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_float_75", 75));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_int32_76", 76));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_int64_77", 77));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_message_78", 78));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sfixed32_79", 79));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sfixed64_80", 80));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sint32_81", 81));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_sint64_82", 82));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_string_83", 83));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_uint32_84", 84));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_int64_uint64_85", 85));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_bool_86", 86));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_bytes_87", 87));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_double_88", 88));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_enum_89", 89));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_fixed32_90", 90));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_fixed64_91", 91));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_float_92", 92));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_int32_93", 93));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_int64_94", 94));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_message_95", 95));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sfixed32_96", 96));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sfixed64_97", 97));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sint32_98", 98));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_sint64_99", 99));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_string_100", 100));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_uint32_101", 101));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed32_uint64_102", 102));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_bool_103", 103));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_bytes_104", 104));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_double_105", 105));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_enum_106", 106));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_fixed32_107", 107));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_fixed64_108", 108));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_float_109", 109));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_int32_110", 110));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_int64_111", 111));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_message_112", 112));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sfixed32_113", 113));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sfixed64_114", 114));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sint32_115", 115));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_sint64_116", 116));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_string_117", 117));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_uint32_118", 118));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sfixed64_uint64_119", 119));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_bool_120", 120));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_bytes_121", 121));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_double_122", 122));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_enum_123", 123));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_fixed32_124", 124));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_fixed64_125", 125));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_float_126", 126));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_int32_127", 127));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_int64_128", 128));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_message_129", 129));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sfixed32_130", 130));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sfixed64_131", 131));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sint32_132", 132));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_sint64_133", 133));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_string_134", 134));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_uint32_135", 135));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint32_uint64_136", 136));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_bool_137", 137));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_bytes_138", 138));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_double_139", 139));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_enum_140", 140));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_fixed32_141", 141));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_fixed64_142", 142));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_float_143", 143));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_int32_144", 144));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_int64_145", 145));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_message_146", 146));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sfixed32_147", 147));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sfixed64_148", 148));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sint32_149", 149));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_sint64_150", 150));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_string_151", 151));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_uint32_152", 152));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_sint64_uint64_153", 153));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_bool_154", 154));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_bytes_155", 155));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_double_156", 156));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_enum_157", 157));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_fixed32_158", 158));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_fixed64_159", 159));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_float_160", 160));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_int32_161", 161));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_int64_162", 162));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_message_163", 163));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sfixed32_164", 164));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sfixed64_165", 165));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sint32_166", 166));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_sint64_167", 167));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_string_168", 168));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_uint32_169", 169));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_string_uint64_170", 170));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_bool_171", 171));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_bytes_172", 172));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_double_173", 173));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_enum_174", 174));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_fixed32_175", 175));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_fixed64_176", 176));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_float_177", 177));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_int32_178", 178));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_int64_179", 179));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_message_180", 180));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sfixed32_181", 181));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sfixed64_182", 182));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sint32_183", 183));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_sint64_184", 184));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_string_185", 185));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_uint32_186", 186));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint32_uint64_187", 187));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_bool_188", 188));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_bytes_189", 189));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_double_190", 190));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_enum_191", 191));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_fixed32_192", 192));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_fixed64_193", 193));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_float_194", 194));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_int32_195", 195));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_int64_196", 196));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_message_197", 197));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sfixed32_198", 198));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sfixed64_199", 199));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sint32_200", 200));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_sint64_201", 201));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_string_202", 202));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_uint32_203", 203));
+ builder.withField(
+ mapFieldInfo(Proto2MessageLiteWithMaps.class, "field_map_uint64_uint64_204", 204));
+
+ return builder.build();
+ }
+
+ private static Field field(Class<?> clazz, String name) {
+ try {
+ return clazz.getDeclaredField(name);
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static FieldInfo mapFieldInfo(Class<?> clazz, String fieldName, int fieldNumber) {
+ try {
+ return forMapField(
+ field(clazz, SchemaUtil.toCamelCase(fieldName, false) + "_"),
+ fieldNumber,
+ SchemaUtil.getMapDefaultEntry(clazz, fieldName),
+ fieldName.contains("_enum_") ? TestEnum.internalGetVerifier() : null);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+}
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index b7b437cea..75e2ae8a8 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -464,6 +464,20 @@ public class JsonFormatTest extends TestCase {
assertEquals(NullValue.NULL_VALUE, message.getOneofNullValue());
}
+ public void testNullMessageInDuplicateOneof() throws Exception {
+ // Succeeds if null is first.
+ TestOneof.Builder successBuilder = TestOneof.newBuilder();
+ mergeFromJson("{\"oneofNestedMessage\": null, \"oneofInt32\": 1}", successBuilder);
+
+ // Fails if null is last.
+ try {
+ TestOneof.Builder builder = TestOneof.newBuilder();
+ mergeFromJson("{\"oneofInt32\": 1, \"oneofNestedMessage\": null}", builder);
+ fail();
+ } catch (InvalidProtocolBufferException expected) {
+ }
+ }
+
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