aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/core/src/main/java/com/google
diff options
context:
space:
mode:
authorGravatar Jisi Liu <jisi.liu@gmail.com>2016-04-28 14:34:59 -0700
committerGravatar Jisi Liu <jisi.liu@gmail.com>2016-04-28 14:34:59 -0700
commitcf14183bcd5485b4a71541599ddce0b35eb71352 (patch)
tree12f6e5eb731d7a70cdac4cdafc8b3131629413e2 /java/core/src/main/java/com/google
parentf00300d7f04f1c38a7d70e271f9232b94dd0e326 (diff)
Down integrate from Google internal.
Diffstat (limited to 'java/core/src/main/java/com/google')
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractMessage.java48
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java79
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractParser.java85
-rw-r--r--java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java48
-rw-r--r--java/core/src/main/java/com/google/protobuf/BooleanArrayList.java69
-rw-r--r--java/core/src/main/java/com/google/protobuf/CodedOutputStream.java2368
-rw-r--r--java/core/src/main/java/com/google/protobuf/Descriptors.java181
-rw-r--r--java/core/src/main/java/com/google/protobuf/DoubleArrayList.java65
-rw-r--r--java/core/src/main/java/com/google/protobuf/DynamicMessage.java40
-rw-r--r--java/core/src/main/java/com/google/protobuf/Extension.java1
-rw-r--r--java/core/src/main/java/com/google/protobuf/FieldSet.java19
-rw-r--r--java/core/src/main/java/com/google/protobuf/FloatArrayList.java64
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessage.java255
-rw-r--r--java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java1067
-rw-r--r--java/core/src/main/java/com/google/protobuf/IntArrayList.java64
-rw-r--r--java/core/src/main/java/com/google/protobuf/Internal.java63
-rw-r--r--java/core/src/main/java/com/google/protobuf/LazyField.java12
-rw-r--r--java/core/src/main/java/com/google/protobuf/LazyFieldLite.java41
-rw-r--r--java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java48
-rw-r--r--java/core/src/main/java/com/google/protobuf/LongArrayList.java64
-rw-r--r--java/core/src/main/java/com/google/protobuf/MapEntryLite.java10
-rw-r--r--java/core/src/main/java/com/google/protobuf/MapField.java3
-rw-r--r--java/core/src/main/java/com/google/protobuf/Message.java70
-rw-r--r--java/core/src/main/java/com/google/protobuf/MessageLite.java21
-rw-r--r--java/core/src/main/java/com/google/protobuf/MessageLiteToString.java151
-rw-r--r--java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/MessageReflection.java107
-rw-r--r--java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java22
-rw-r--r--java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java1
-rw-r--r--java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java8
-rw-r--r--java/core/src/main/java/com/google/protobuf/RpcUtil.java4
-rw-r--r--java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/SmallSortedMap.java106
-rw-r--r--java/core/src/main/java/com/google/protobuf/TextFormat.java2
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java77
-rw-r--r--java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java50
-rw-r--r--java/core/src/main/java/com/google/protobuf/WireFormat.java19
37 files changed, 4088 insertions, 1248 deletions
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
index 9f418f2b..03c0d579 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -50,17 +50,23 @@ import java.util.Map;
*
* @author kenton@google.com Kenton Varda
*/
-public abstract class AbstractMessage extends AbstractMessageLite
- implements Message {
+public abstract class AbstractMessage
+ // TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.
+ extends AbstractMessageLite
+ implements Message {
+
+ @Override
public boolean isInitialized() {
return MessageReflection.isInitialized(this);
}
+ @Override
public List<String> findInitializationErrors() {
return MessageReflection.findMissingFields(this);
}
+ @Override
public String getInitializationErrorString() {
return MessageReflection.delimitWithCommas(findInitializationErrors());
}
@@ -83,12 +89,14 @@ public abstract class AbstractMessage extends AbstractMessageLite
return TextFormat.printToString(this);
}
+ @Override
public void writeTo(final CodedOutputStream output) throws IOException {
MessageReflection.writeMessageTo(this, getAllFields(), output, false);
}
protected int memoizedSize = -1;
+ @Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) {
@@ -288,8 +296,8 @@ public abstract class AbstractMessage extends AbstractMessageLite
* other methods.
*/
@SuppressWarnings("unchecked")
- public static abstract class Builder<BuilderType extends Builder>
- extends AbstractMessageLite.Builder<BuilderType>
+ public static abstract class Builder<BuilderType extends Builder<BuilderType>>
+ extends AbstractMessageLite.Builder
implements Message.Builder {
// The compiler produces an error if this is not declared explicitly.
@Override
@@ -314,6 +322,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
throw new UnsupportedOperationException("clearOneof() is not implemented.");
}
+ @Override
public BuilderType clear() {
for (final Map.Entry<FieldDescriptor, Object> entry :
getAllFields().entrySet()) {
@@ -322,14 +331,22 @@ public abstract class AbstractMessage extends AbstractMessageLite
return (BuilderType) this;
}
+ @Override
public List<String> findInitializationErrors() {
return MessageReflection.findMissingFields(this);
}
+ @Override
public String getInitializationErrorString() {
return MessageReflection.delimitWithCommas(findInitializationErrors());
}
+
+ @Override
+ protected BuilderType internalMergeFrom(AbstractMessageLite other) {
+ return mergeFrom((Message) other);
+ }
+ @Override
public BuilderType mergeFrom(final Message other) {
if (other.getDescriptorForType() != getDescriptorForType()) {
throw new IllegalArgumentException(
@@ -407,6 +424,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
return (BuilderType) this;
}
+ @Override
public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
setUnknownFields(
UnknownFieldSet.newBuilder(getUnknownFields())
@@ -415,17 +433,19 @@ public abstract class AbstractMessage extends AbstractMessageLite
return (BuilderType) this;
}
+ @Override
public Message.Builder getFieldBuilder(final FieldDescriptor field) {
throw new UnsupportedOperationException(
"getFieldBuilder() called on an unsupported message type.");
}
- public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
- int index) {
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on an unsupported message type.");
}
+ @Override
public String toString() {
return TextFormat.printToString(this);
}
@@ -462,7 +482,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
@Override
public BuilderType mergeFrom(final ByteString data)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data);
+ return (BuilderType) super.mergeFrom(data);
}
@Override
@@ -470,20 +490,20 @@ public abstract class AbstractMessage extends AbstractMessageLite
final ByteString data,
final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data, extensionRegistry);
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
}
@Override
public BuilderType mergeFrom(final byte[] data)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data);
+ return (BuilderType) super.mergeFrom(data);
}
@Override
public BuilderType mergeFrom(
final byte[] data, final int off, final int len)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data, off, len);
+ return (BuilderType) super.mergeFrom(data, off, len);
}
@Override
@@ -491,7 +511,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
final byte[] data,
final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data, extensionRegistry);
+ return (BuilderType) super.mergeFrom(data, extensionRegistry);
}
@Override
@@ -499,13 +519,13 @@ public abstract class AbstractMessage extends AbstractMessageLite
final byte[] data, final int off, final int len,
final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- return super.mergeFrom(data, off, len, extensionRegistry);
+ return (BuilderType) super.mergeFrom(data, off, len, extensionRegistry);
}
@Override
public BuilderType mergeFrom(final InputStream input)
throws IOException {
- return super.mergeFrom(input);
+ return (BuilderType) super.mergeFrom(input);
}
@Override
@@ -513,7 +533,7 @@ public abstract class AbstractMessage extends AbstractMessageLite
final InputStream input,
final ExtensionRegistryLite extensionRegistry)
throws IOException {
- return super.mergeFrom(input, extensionRegistry);
+ return (BuilderType) super.mergeFrom(input, extensionRegistry);
}
@Override
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 12384983..43736dd1 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -43,9 +43,13 @@ import java.util.Collection;
*
* @author kenton@google.com Kenton Varda
*/
-public abstract class AbstractMessageLite implements MessageLite {
+public abstract class AbstractMessageLite<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends AbstractMessageLite.Builder<MessageType, BuilderType>>
+ implements MessageLite {
protected int memoizedHashCode = 0;
-
+
+ @Override
public ByteString toByteString() {
try {
final ByteString.CodedBuilder out =
@@ -59,6 +63,7 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ @Override
public byte[] toByteArray() {
try {
final byte[] result = new byte[getSerializedSize()];
@@ -73,6 +78,7 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ @Override
public void writeTo(final OutputStream output) throws IOException {
final int bufferSize =
CodedOutputStream.computePreferredBufferSize(getSerializedSize());
@@ -82,6 +88,7 @@ public abstract class AbstractMessageLite implements MessageLite {
codedOutput.flush();
}
+ @Override
public void writeDelimitedTo(final OutputStream output) throws IOException {
final int serialized = getSerializedSize();
final int bufferSize = CodedOutputStream.computePreferredBufferSize(
@@ -120,25 +127,27 @@ public abstract class AbstractMessageLite implements MessageLite {
* other methods.
*/
@SuppressWarnings("unchecked")
- public static abstract class Builder<BuilderType extends Builder>
+ public abstract static class Builder<
+ MessageType extends AbstractMessageLite<MessageType, BuilderType>,
+ BuilderType extends Builder<MessageType, BuilderType>>
implements MessageLite.Builder {
// The compiler produces an error if this is not declared explicitly.
@Override
public abstract BuilderType clone();
- public BuilderType mergeFrom(final CodedInputStream input)
- throws IOException {
+ @Override
+ public BuilderType mergeFrom(final CodedInputStream input) throws IOException {
return mergeFrom(input, ExtensionRegistryLite.getEmptyRegistry());
}
// Re-defined here for return type covariance.
+ @Override
public abstract BuilderType mergeFrom(
- final CodedInputStream input,
- final ExtensionRegistryLite extensionRegistry)
+ final CodedInputStream input, final ExtensionRegistryLite extensionRegistry)
throws IOException;
- public BuilderType mergeFrom(final ByteString data)
- throws InvalidProtocolBufferException {
+ @Override
+ public BuilderType mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
try {
final CodedInputStream input = data.newCodedInput();
mergeFrom(input);
@@ -153,9 +162,9 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ @Override
public BuilderType mergeFrom(
- final ByteString data,
- final ExtensionRegistryLite extensionRegistry)
+ final ByteString data, final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
try {
final CodedInputStream input = data.newCodedInput();
@@ -171,14 +180,14 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
- public BuilderType mergeFrom(final byte[] data)
- throws InvalidProtocolBufferException {
+ @Override
+ public BuilderType mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
return mergeFrom(data, 0, data.length);
}
- public BuilderType mergeFrom(final byte[] data, final int off,
- final int len)
- throws InvalidProtocolBufferException {
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final int off, final int len)
+ throws InvalidProtocolBufferException {
try {
final CodedInputStream input =
CodedInputStream.newInstance(data, off, len);
@@ -194,15 +203,17 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
- public BuilderType mergeFrom(
- final byte[] data,
- final ExtensionRegistryLite extensionRegistry)
+ @Override
+ public BuilderType mergeFrom(final byte[] data, final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return mergeFrom(data, 0, data.length, extensionRegistry);
}
+ @Override
public BuilderType mergeFrom(
- final byte[] data, final int off, final int len,
+ final byte[] data,
+ final int off,
+ final int len,
final ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
try {
@@ -220,6 +231,7 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ @Override
public BuilderType mergeFrom(final InputStream input) throws IOException {
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
mergeFrom(codedInput);
@@ -227,10 +239,9 @@ public abstract class AbstractMessageLite implements MessageLite {
return (BuilderType) this;
}
+ @Override
public BuilderType mergeFrom(
- final InputStream input,
- final ExtensionRegistryLite extensionRegistry)
- throws IOException {
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
mergeFrom(codedInput, extensionRegistry);
codedInput.checkLastTagWas(0);
@@ -292,10 +303,9 @@ public abstract class AbstractMessageLite implements MessageLite {
}
}
+ @Override
public boolean mergeDelimitedFrom(
- final InputStream input,
- final ExtensionRegistryLite extensionRegistry)
- throws IOException {
+ final InputStream input, final ExtensionRegistryLite extensionRegistry) throws IOException {
final int firstByte = input.read();
if (firstByte == -1) {
return false;
@@ -306,11 +316,24 @@ public abstract class AbstractMessageLite implements MessageLite {
return true;
}
- public boolean mergeDelimitedFrom(final InputStream input)
- throws IOException {
+ @Override
+ public boolean mergeDelimitedFrom(final InputStream input) throws IOException {
return mergeDelimitedFrom(input,
ExtensionRegistryLite.getEmptyRegistry());
}
+
+ @Override
+ @SuppressWarnings("unchecked") // isInstance takes care of this
+ public BuilderType mergeFrom(final MessageLite other) {
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ throw new IllegalArgumentException(
+ "mergeFrom(MessageLite) can only merge messages of the same type.");
+ }
+
+ return internalMergeFrom((MessageType) other);
+ }
+
+ protected abstract BuilderType internalMergeFrom(MessageType message);
/**
* Construct an UninitializedMessageException reporting missing fields in
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractParser.java b/java/core/src/main/java/com/google/protobuf/AbstractParser.java
index 1a4c6311..66b0ee3b 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractParser.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractParser.java
@@ -78,26 +78,27 @@ public abstract class AbstractParser<MessageType extends MessageLite>
private static final ExtensionRegistryLite EMPTY_REGISTRY
= ExtensionRegistryLite.getEmptyRegistry();
+ @Override
public MessageType parsePartialFrom(CodedInputStream input)
throws InvalidProtocolBufferException {
return parsePartialFrom(input, EMPTY_REGISTRY);
}
- public MessageType parseFrom(CodedInputStream input,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(input, extensionRegistry));
}
- public MessageType parseFrom(CodedInputStream input)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parseFrom(CodedInputStream input) throws InvalidProtocolBufferException {
return parseFrom(input, EMPTY_REGISTRY);
}
- public MessageType parsePartialFrom(ByteString data,
- ExtensionRegistryLite extensionRegistry)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parsePartialFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException {
MessageType message;
try {
CodedInputStream input = data.newCodedInput();
@@ -113,24 +114,25 @@ public abstract class AbstractParser<MessageType extends MessageLite>
}
}
- public MessageType parsePartialFrom(ByteString data)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parsePartialFrom(ByteString data) throws InvalidProtocolBufferException {
return parsePartialFrom(data, EMPTY_REGISTRY);
}
- public MessageType parseFrom(ByteString data,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(parsePartialFrom(data, extensionRegistry));
}
- public MessageType parseFrom(ByteString data)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parseFrom(ByteString data) throws InvalidProtocolBufferException {
return parseFrom(data, EMPTY_REGISTRY);
}
- public MessageType parsePartialFrom(byte[] data, int off, int len,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parsePartialFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
try {
CodedInputStream input = CodedInputStream.newInstance(data, off, len);
@@ -146,47 +148,50 @@ public abstract class AbstractParser<MessageType extends MessageLite>
}
}
+ @Override
public MessageType parsePartialFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, off, len, EMPTY_REGISTRY);
}
- public MessageType parsePartialFrom(byte[] data,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parsePartialFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return parsePartialFrom(data, 0, data.length, extensionRegistry);
}
- public MessageType parsePartialFrom(byte[] data)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parsePartialFrom(byte[] data) throws InvalidProtocolBufferException {
return parsePartialFrom(data, 0, data.length, EMPTY_REGISTRY);
}
- public MessageType parseFrom(byte[] data, int off, int len,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseFrom(
+ byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(data, off, len, extensionRegistry));
}
+ @Override
public MessageType parseFrom(byte[] data, int off, int len)
throws InvalidProtocolBufferException {
return parseFrom(data, off, len, EMPTY_REGISTRY);
}
- public MessageType parseFrom(byte[] data,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return parseFrom(data, 0, data.length, extensionRegistry);
}
- public MessageType parseFrom(byte[] data)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parseFrom(byte[] data) throws InvalidProtocolBufferException {
return parseFrom(data, EMPTY_REGISTRY);
}
- public MessageType parsePartialFrom(InputStream input,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parsePartialFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
CodedInputStream codedInput = CodedInputStream.newInstance(input);
MessageType message = parsePartialFrom(codedInput, extensionRegistry);
@@ -198,26 +203,26 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return message;
}
- public MessageType parsePartialFrom(InputStream input)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parsePartialFrom(InputStream input) throws InvalidProtocolBufferException {
return parsePartialFrom(input, EMPTY_REGISTRY);
}
- public MessageType parseFrom(InputStream input,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialFrom(input, extensionRegistry));
}
- public MessageType parseFrom(InputStream input)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parseFrom(InputStream input) throws InvalidProtocolBufferException {
return parseFrom(input, EMPTY_REGISTRY);
}
+ @Override
public MessageType parsePartialDelimitedFrom(
- InputStream input,
- ExtensionRegistryLite extensionRegistry)
+ InputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
int size;
try {
@@ -233,21 +238,21 @@ public abstract class AbstractParser<MessageType extends MessageLite>
return parsePartialFrom(limitedInput, extensionRegistry);
}
+ @Override
public MessageType parsePartialDelimitedFrom(InputStream input)
throws InvalidProtocolBufferException {
return parsePartialDelimitedFrom(input, EMPTY_REGISTRY);
}
- public MessageType parseDelimitedFrom(
- InputStream input,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
return checkMessageInitialized(
parsePartialDelimitedFrom(input, extensionRegistry));
}
- public MessageType parseDelimitedFrom(InputStream input)
- throws InvalidProtocolBufferException {
+ @Override
+ public MessageType parseDelimitedFrom(InputStream input) throws InvalidProtocolBufferException {
return parseDelimitedFrom(input, EMPTY_REGISTRY);
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
index bb6446b2..b17db6e0 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java
@@ -34,19 +34,25 @@ import com.google.protobuf.Internal.ProtobufList;
import java.util.AbstractList;
import java.util.Collection;
+import java.util.List;
+import java.util.RandomAccess;
/**
* An abstract implementation of {@link ProtobufList} which manages mutability semantics. All mutate
- * methods are check if the list is mutable before proceeding. Subclasses must invoke
+ * methods must check if the list is mutable before proceeding. Subclasses must invoke
* {@link #ensureIsMutable()} manually when overriding those methods.
+ * <p>
+ * This implementation assumes all subclasses are array based, supporting random access.
*/
abstract class AbstractProtobufList<E> extends AbstractList<E> implements ProtobufList<E> {
+ protected static final int DEFAULT_CAPACITY = 10;
+
/**
* Whether or not this list is modifiable.
*/
private boolean isMutable;
-
+
/**
* Constructs a mutable list by default.
*/
@@ -55,6 +61,44 @@ abstract class AbstractProtobufList<E> extends AbstractList<E> implements Protob
}
@Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof List)) {
+ return false;
+ }
+ // Handle lists that do not support RandomAccess as efficiently as possible by using an iterator
+ // based approach in our super class. Otherwise our index based approach will avoid those
+ // allocations.
+ if (!(o instanceof RandomAccess)) {
+ return super.equals(o);
+ }
+
+ List<?> other = (List<?>) o;
+ final int size = size();
+ if (size != other.size()) {
+ return false;
+ }
+ for (int i = 0; i < size; i++) {
+ if (!get(i).equals(other.get(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int size = size();
+ int hashCode = 1;
+ for (int i = 0; i < size; i++) {
+ hashCode = (31 * hashCode) + get(i).hashCode();
+ }
+ return hashCode;
+ }
+
+ @Override
public boolean add(E e) {
ensureIsMutable();
return super.add(e);
diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
index 70e042f5..8b2820b6 100644
--- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.BooleanList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.RandomAccess;
/**
@@ -45,8 +44,6 @@ import java.util.RandomAccess;
final class BooleanArrayList
extends AbstractProtobufList<Boolean> implements BooleanList, RandomAccess {
- private static final int DEFAULT_CAPACITY = 10;
-
private static final BooleanArrayList EMPTY_LIST = new BooleanArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -60,7 +57,7 @@ final class BooleanArrayList
* The backing store for the list.
*/
private boolean[] array;
-
+
/**
* The size of the list distinct from the length of the array. That is, it is the number of
* elements set in the list.
@@ -71,35 +68,57 @@ final class BooleanArrayList
* Constructs a new mutable {@code BooleanArrayList} with default capacity.
*/
BooleanArrayList() {
- this(DEFAULT_CAPACITY);
+ this(new boolean[DEFAULT_CAPACITY], 0);
}
/**
- * Constructs a new mutable {@code BooleanArrayList} with the provided capacity.
+ * Constructs a new mutable {@code BooleanArrayList}.
*/
- BooleanArrayList(int capacity) {
- array = new boolean[capacity];
- size = 0;
+ private BooleanArrayList(boolean[] array, int size) {
+ this.array = array;
+ this.size = size;
}
-
- /**
- * Constructs a new mutable {@code BooleanArrayList} containing the same elements as
- * {@code other}.
- */
- BooleanArrayList(List<Boolean> other) {
- if (other instanceof BooleanArrayList) {
- BooleanArrayList list = (BooleanArrayList) other;
- array = list.array.clone();
- size = list.size;
- } else {
- size = other.size();
- array = new boolean[size];
- for (int i = 0; i < size; i++) {
- array[i] = other.get(i);
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof BooleanArrayList)) {
+ return super.equals(o);
+ }
+ BooleanArrayList other = (BooleanArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final boolean[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
}
}
+
+ return true;
}
-
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Internal.hashBoolean(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public BooleanList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new BooleanArrayList(Arrays.copyOf(array, capacity), size);
+ }
+
@Override
public Boolean get(int index) {
return getBoolean(index);
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 b92394b8..ad174d0f 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,11 +30,18 @@
package com.google.protobuf;
+import static java.lang.Math.max;
+
import com.google.protobuf.Utf8.UnpairedSurrogateException;
import java.io.IOException;
import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -50,23 +57,21 @@ import java.util.logging.Logger;
*
* <p>This class is totally unsynchronized.
*/
-public final class CodedOutputStream {
+public abstract class CodedOutputStream extends ByteOutput {
private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
+ private static final sun.misc.Unsafe UNSAFE = getUnsafe();
+ private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
+ private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
- private static final int LITTLE_ENDIAN_64_SIZE = 8;
+ private static final int FIXED_32_SIZE = 4;
+ private static final int FIXED_64_SIZE = 8;
+ private static final int MAX_VARINT_SIZE = 10;
/**
* @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
*/
- @Deprecated public static final int LITTLE_ENDIAN_32_SIZE = 4;
-
- // TODO(dweis): Consider migrating to a ByteBuffer.
- private final byte[] buffer;
- private final int limit;
- private int position;
- private int totalBytesWritten = 0;
-
- private final OutputStream output;
+ @Deprecated
+ public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
/**
* The buffer size used in {@link #newInstance(OutputStream)}.
@@ -87,34 +92,27 @@ public final class CodedOutputStream {
return dataLength;
}
- private CodedOutputStream(final byte[] buffer, final int offset, final int length) {
- output = null;
- this.buffer = buffer;
- position = offset;
- limit = offset + length;
- }
-
- private CodedOutputStream(final OutputStream output, final byte[] buffer) {
- this.output = output;
- this.buffer = buffer;
- position = 0;
- limit = buffer.length;
- }
-
/**
- * Create a new {@code CodedOutputStream} wrapping the given
- * {@code OutputStream}.
+ * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream}.
+ *
+ * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+ * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+ * difficult to debug.
*/
public static CodedOutputStream newInstance(final OutputStream output) {
return newInstance(output, DEFAULT_BUFFER_SIZE);
}
/**
- * Create a new {@code CodedOutputStream} wrapping the given
- * {@code OutputStream} with a given buffer size.
+ * Create a new {@code CodedOutputStream} wrapping the given {@code OutputStream} with a given
+ * buffer size.
+ *
+ * <p> NOTE: The provided {@link OutputStream} <strong>MUST NOT</strong> retain access or
+ * modify the provided byte arrays. Doing so may result in corrupted data, which would be
+ * difficult to debug.
*/
public static CodedOutputStream newInstance(final OutputStream output, final int bufferSize) {
- return new CodedOutputStream(output, new byte[bufferSize]);
+ return new OutputStreamEncoder(output, bufferSize);
}
/**
@@ -137,160 +135,144 @@ public final class CodedOutputStream {
*/
public static CodedOutputStream newInstance(
final byte[] flatArray, final int offset, final int length) {
- return new CodedOutputStream(flatArray, offset, length);
+ return new ArrayEncoder(flatArray, offset, length);
}
/**
- * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer.
+ * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
*/
public static CodedOutputStream newInstance(ByteBuffer byteBuffer) {
- return newInstance(byteBuffer, DEFAULT_BUFFER_SIZE);
+ if (byteBuffer.hasArray()) {
+ return new NioHeapEncoder(byteBuffer);
+ }
+ return new NioEncoder(byteBuffer);
}
/**
- * Create a new {@code CodedOutputStream} that writes to the given ByteBuffer.
+ * Create a new {@code CodedOutputStream} that writes to the given {@link ByteBuffer}.
+ *
+ * @deprecated the size parameter is no longer used since use of an internal buffer is useless
+ * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstance(ByteBuffer)}
+ * instead.
*/
- public static CodedOutputStream newInstance(ByteBuffer byteBuffer, int bufferSize) {
- return newInstance(new ByteBufferOutputStream(byteBuffer), bufferSize);
+ @Deprecated
+ public static CodedOutputStream newInstance(ByteBuffer byteBuffer,
+ @SuppressWarnings("unused") int unused) {
+ return newInstance(byteBuffer);
}
- private static class ByteBufferOutputStream extends OutputStream {
- private final ByteBuffer byteBuffer;
-
- public ByteBufferOutputStream(ByteBuffer byteBuffer) {
- this.byteBuffer = byteBuffer;
+ /**
+ * Create a new {@code CodedOutputStream} that writes to the provided {@link ByteOutput}.
+ *
+ * <p> NOTE: The {@link ByteOutput} <strong>MUST NOT</strong> modify the provided buffers. Doing
+ * so may result in corrupted data, which would be difficult to debug.
+ *
+ * @param byteOutput the output target for encoded bytes.
+ * @param bufferSize the size of the internal scratch buffer to be used for string encoding.
+ * Setting this to {@code 0} will disable buffering, requiring an allocation for each encoded
+ * string.
+ */
+ static CodedOutputStream newInstance(ByteOutput byteOutput, int bufferSize) {
+ if (bufferSize < 0) {
+ throw new IllegalArgumentException("bufferSize must be positive");
}
- @Override
- public void write(int b) throws IOException {
- byteBuffer.put((byte) b);
- }
+ return new ByteOutputEncoder(byteOutput, bufferSize);
+ }
- @Override
- public void write(byte[] data, int offset, int length) throws IOException {
- byteBuffer.put(data, offset, length);
- }
+ // Disallow construction outside of this class.
+ private CodedOutputStream() {
}
// -----------------------------------------------------------------
/** Encode and write a tag. */
- public void writeTag(final int fieldNumber, final int wireType) throws IOException {
- writeRawVarint32(WireFormat.makeTag(fieldNumber, wireType));
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeTag(int fieldNumber, int wireType) throws IOException;
/** Write an {@code int32} field, including tag, to the stream. */
- public void writeInt32(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeInt32NoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeInt32(int fieldNumber, int value) throws IOException;
/** Write a {@code uint32} field, including tag, to the stream. */
- public void writeUInt32(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeUInt32NoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt32(int fieldNumber, int value) throws IOException;
/** Write a {@code sint32} field, including tag, to the stream. */
- public void writeSInt32(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeSInt32NoTag(value);
+ public final void writeSInt32(final int fieldNumber, final int value) throws IOException {
+ writeUInt32(fieldNumber, encodeZigZag32(value));
}
/** Write a {@code fixed32} field, including tag, to the stream. */
- public void writeFixed32(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeFixed32NoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed32(int fieldNumber, int value) throws IOException;
/** Write an {@code sfixed32} field, including tag, to the stream. */
- public void writeSFixed32(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeSFixed32NoTag(value);
+ public final void writeSFixed32(final int fieldNumber, final int value) throws IOException {
+ writeFixed32(fieldNumber, value);
}
/** Write an {@code int64} field, including tag, to the stream. */
- public void writeInt64(final int fieldNumber, final long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeInt64NoTag(value);
+ public final void writeInt64(final int fieldNumber, final long value) throws IOException {
+ writeUInt64(fieldNumber, value);
}
/** Write a {@code uint64} field, including tag, to the stream. */
- public void writeUInt64(final int fieldNumber, final long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeUInt64NoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt64(int fieldNumber, long value) throws IOException;
/** Write an {@code sint64} field, including tag, to the stream. */
- public void writeSInt64(final int fieldNumber, final long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeSInt64NoTag(value);
+ public final void writeSInt64(final int fieldNumber, final long value) throws IOException {
+ writeUInt64(fieldNumber, encodeZigZag64(value));
}
/** Write a {@code fixed64} field, including tag, to the stream. */
- public void writeFixed64(final int fieldNumber, final long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeFixed64NoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed64(int fieldNumber, long value) throws IOException;
/** Write an {@code sfixed64} field, including tag, to the stream. */
- public void writeSFixed64(final int fieldNumber, final long value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeSFixed64NoTag(value);
+ public final void writeSFixed64(final int fieldNumber, final long value) throws IOException {
+ writeFixed64(fieldNumber, value);
}
/** Write a {@code float} field, including tag, to the stream. */
- public void writeFloat(final int fieldNumber, final float value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
- writeFloatNoTag(value);
+ public final void writeFloat(final int fieldNumber, final float value) throws IOException {
+ writeFixed32(fieldNumber, Float.floatToRawIntBits(value));
}
/** Write a {@code double} field, including tag, to the stream. */
- public void writeDouble(final int fieldNumber, final double value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
- writeDoubleNoTag(value);
+ public final void writeDouble(final int fieldNumber, final double value) throws IOException {
+ writeFixed64(fieldNumber, Double.doubleToRawLongBits(value));
}
/** Write a {@code bool} field, including tag, to the stream. */
- public void writeBool(final int fieldNumber, final boolean value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeBoolNoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBool(int fieldNumber, boolean value) throws IOException;
/**
* Write an enum field, including tag, to the stream. The provided value is the numeric
* value used to represent the enum value on the wire (not the enum ordinal value).
*/
- public void writeEnum(final int fieldNumber, final int value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
- writeEnumNoTag(value);
+ public final void writeEnum(final int fieldNumber, final int value) throws IOException {
+ writeInt32(fieldNumber, value);
}
/** Write a {@code string} field, including tag, to the stream. */
- public void writeString(final int fieldNumber, final String value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeStringNoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeString(int fieldNumber, String value) throws IOException;
/** Write a {@code bytes} field, including tag, to the stream. */
- public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeBytesNoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBytes(int fieldNumber, ByteString value) throws IOException;
/** Write a {@code bytes} field, including tag, to the stream. */
- public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeByteArrayNoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteArray(int fieldNumber, byte[] value) throws IOException;
/** Write a {@code bytes} field, including tag, to the stream. */
- public void writeByteArray(
- final int fieldNumber, final byte[] value, final int offset, final int length)
- throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeByteArrayNoTag(value, offset, length);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteArray(int fieldNumber, byte[] value, int offset, int length)
+ throws IOException;
/**
* Write a {@code bytes} field, including tag, to the stream.
@@ -302,67 +284,36 @@ public final class CodedOutputStream {
* of a ByteBuffer, you can call
* {@code writeByteBuffer(fieldNumber, byteBuffer.slice())}.
*/
- public void writeByteBuffer(final int fieldNumber, final ByteBuffer value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeByteBufferNoTag(value);
- }
-
- /** Write a single byte. */
- public void writeRawByte(final byte value) throws IOException {
- if (position == limit) {
- refreshBuffer();
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOException;
- buffer[position++] = value;
- ++totalBytesWritten;
+ /**
+ * Write a single byte.
+ */
+ public final void writeRawByte(final byte value) throws IOException {
+ write(value);
}
/** Write a single byte, represented by an integer value. */
- public void writeRawByte(final int value) throws IOException {
- writeRawByte((byte) value);
+ public final void writeRawByte(final int value) throws IOException {
+ write((byte) value);
}
/** Write an array of bytes. */
- public void writeRawBytes(final byte[] value) throws IOException {
- writeRawBytes(value, 0, value.length);
+ public final void writeRawBytes(final byte[] value) throws IOException {
+ write(value, 0, value.length);
}
- /** Write part of an array of bytes. */
- public void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
- if (limit - position >= length) {
- // We have room in the current buffer.
- System.arraycopy(value, offset, buffer, position, length);
- position += length;
- totalBytesWritten += length;
- } else {
- // Write extends past current buffer. Fill the rest of this buffer and
- // flush.
- final int bytesWritten = limit - position;
- System.arraycopy(value, offset, buffer, position, bytesWritten);
- offset += bytesWritten;
- length -= bytesWritten;
- position = limit;
- totalBytesWritten += bytesWritten;
- refreshBuffer();
-
- // Now deal with the rest.
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- if (length <= limit) {
- // Fits in new buffer.
- System.arraycopy(value, offset, buffer, 0, length);
- position = length;
- } else {
- // Write is very big. Let's do it all at once.
- output.write(value, offset, length);
- }
- totalBytesWritten += length;
- }
+ /**
+ * Write part of an array of bytes.
+ */
+ public final void writeRawBytes(final byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
}
/** Write a byte string. */
- public void writeRawBytes(final ByteString value) throws IOException {
- writeRawBytes(value, 0, value.size());
+ public final void writeRawBytes(final ByteString value) throws IOException {
+ value.writeTo(this);
}
/**
@@ -374,155 +325,138 @@ public final class CodedOutputStream {
* write the remaining bytes of a ByteBuffer, you can call
* {@code writeRawBytes(byteBuffer.slice())}.
*/
- public void writeRawBytes(final ByteBuffer value) throws IOException {
- if (value.hasArray()) {
- writeRawBytes(value.array(), value.arrayOffset(), value.capacity());
- } else {
- ByteBuffer duplicated = value.duplicate();
- duplicated.clear();
- writeRawBytesInternal(duplicated);
- }
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeRawBytes(final ByteBuffer value) throws IOException;
/** Write an embedded message field, including tag, to the stream. */
- public void writeMessage(final int fieldNumber, final MessageLite value) throws IOException {
- writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
- writeMessageNoTag(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException;
/**
* Write a MessageSet extension field to the stream. For historical reasons,
* the wire format differs from normal fields.
*/
- public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
- throws IOException {
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
- writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
- writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException;
/**
* Write an unparsed MessageSet extension field to the stream. For
* historical reasons, the wire format differs from normal fields.
*/
- public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
- throws IOException {
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
- writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
- writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
- writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException;
// -----------------------------------------------------------------
/** Write an {@code int32} field to the stream. */
- public void writeInt32NoTag(final int value) throws IOException {
- if (value >= 0) {
- writeRawVarint32(value);
- } else {
- // Must sign-extend.
- writeRawVarint64(value);
- }
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeInt32NoTag(final int value) throws IOException;
/** Write a {@code uint32} field to the stream. */
- public void writeUInt32NoTag(final int value) throws IOException {
- writeRawVarint32(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt32NoTag(int value) throws IOException;
/** Write a {@code sint32} field to the stream. */
- public void writeSInt32NoTag(final int value) throws IOException {
- writeRawVarint32(encodeZigZag32(value));
+ public final void writeSInt32NoTag(final int value) throws IOException {
+ writeUInt32NoTag(encodeZigZag32(value));
}
/** Write a {@code fixed32} field to the stream. */
- public void writeFixed32NoTag(final int value) throws IOException {
- writeRawLittleEndian32(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed32NoTag(int value) throws IOException;
/** Write a {@code sfixed32} field to the stream. */
- public void writeSFixed32NoTag(final int value) throws IOException {
- writeRawLittleEndian32(value);
+ public final void writeSFixed32NoTag(final int value) throws IOException {
+ writeFixed32NoTag(value);
}
/** Write an {@code int64} field to the stream. */
- public void writeInt64NoTag(final long value) throws IOException {
- writeRawVarint64(value);
+ public final void writeInt64NoTag(final long value) throws IOException {
+ writeUInt64NoTag(value);
}
/** Write a {@code uint64} field to the stream. */
- public void writeUInt64NoTag(final long value) throws IOException {
- writeRawVarint64(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeUInt64NoTag(long value) throws IOException;
/** Write a {@code sint64} field to the stream. */
- public void writeSInt64NoTag(final long value) throws IOException {
- writeRawVarint64(encodeZigZag64(value));
+ public final void writeSInt64NoTag(final long value) throws IOException {
+ writeUInt64NoTag(encodeZigZag64(value));
}
/** Write a {@code fixed64} field to the stream. */
- public void writeFixed64NoTag(final long value) throws IOException {
- writeRawLittleEndian64(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeFixed64NoTag(long value) throws IOException;
/** Write a {@code sfixed64} field to the stream. */
- public void writeSFixed64NoTag(final long value) throws IOException {
- writeRawLittleEndian64(value);
+ public final void writeSFixed64NoTag(final long value) throws IOException {
+ writeFixed64NoTag(value);
}
/** Write a {@code float} field to the stream. */
- public void writeFloatNoTag(final float value) throws IOException {
- writeRawLittleEndian32(Float.floatToRawIntBits(value));
+ public final void writeFloatNoTag(final float value) throws IOException {
+ writeFixed32NoTag(Float.floatToRawIntBits(value));
}
/** Write a {@code double} field to the stream. */
- public void writeDoubleNoTag(final double value) throws IOException {
- writeRawLittleEndian64(Double.doubleToRawLongBits(value));
+ public final void writeDoubleNoTag(final double value) throws IOException {
+ writeFixed64NoTag(Double.doubleToRawLongBits(value));
}
/** Write a {@code bool} field to the stream. */
- public void writeBoolNoTag(final boolean value) throws IOException {
- writeRawByte(value ? 1 : 0);
+ public final void writeBoolNoTag(final boolean value) throws IOException {
+ write((byte) (value ? 1 : 0));
}
/**
* Write an enum field to the stream. The provided value is the numeric
* value used to represent the enum value on the wire (not the enum ordinal value).
*/
- public void writeEnumNoTag(final int value) throws IOException {
+ public final void writeEnumNoTag(final int value) throws IOException {
writeInt32NoTag(value);
}
/** Write a {@code string} field to the stream. */
// TODO(dweis): Document behavior on ill-formed UTF-16 input.
- public void writeStringNoTag(final String value) throws IOException {
- try {
- efficientWriteStringNoTag(value);
- } catch (UnpairedSurrogateException e) {
- logger.log(Level.WARNING,
- "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", e);
- inefficientWriteStringNoTag(value);
- }
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeStringNoTag(String value) throws IOException;
/** Write a {@code bytes} field to the stream. */
- public void writeBytesNoTag(final ByteString value) throws IOException {
- writeRawVarint32(value.size());
- writeRawBytes(value);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeBytesNoTag(final ByteString value) throws IOException;
/** Write a {@code bytes} field to the stream. */
- public void writeByteArrayNoTag(final byte[] value) throws IOException {
- writeRawVarint32(value.length);
- writeRawBytes(value);
+ public final void writeByteArrayNoTag(final byte[] value) throws IOException {
+ writeByteArrayNoTag(value, 0, value.length);
}
/** Write an embedded message field to the stream. */
- public void writeMessageNoTag(final MessageLite value) throws IOException {
- writeRawVarint32(value.getSerializedSize());
- value.writeTo(this);
- }
+ // Abstract to avoid overhead of additional virtual method calls.
+ public abstract void writeMessageNoTag(final MessageLite value) throws IOException;
+
+ //=================================================================
+
+ @ExperimentalApi
+ @Override
+ public abstract void write(byte value) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void write(byte[] value, int offset, int length) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void writeLazy(byte[] value, int offset, int length) throws IOException;
+
+ @Override
+ public abstract void write(ByteBuffer value) throws IOException;
+
+ @ExperimentalApi
+ @Override
+ public abstract void writeLazy(ByteBuffer value) throws IOException;
// =================================================================
// =================================================================
@@ -727,7 +661,7 @@ public final class CodedOutputStream {
/** Compute the number of bytes that would be needed to encode a tag. */
public static int computeTagSize(final int fieldNumber) {
- return computeRawVarint32Size(WireFormat.makeTag(fieldNumber, 0));
+ return computeUInt32SizeNoTag(WireFormat.makeTag(fieldNumber, 0));
}
/**
@@ -736,10 +670,10 @@ public final class CodedOutputStream {
*/
public static int computeInt32SizeNoTag(final int value) {
if (value >= 0) {
- return computeRawVarint32Size(value);
+ return computeUInt32SizeNoTag(value);
} else {
// Must sign-extend.
- return 10;
+ return MAX_VARINT_SIZE;
}
}
@@ -748,7 +682,19 @@ public final class CodedOutputStream {
* {@code uint32} field.
*/
public static int computeUInt32SizeNoTag(final int value) {
- return computeRawVarint32Size(value);
+ if ((value & (~0 << 7)) == 0) {
+ return 1;
+ }
+ if ((value & (~0 << 14)) == 0) {
+ return 2;
+ }
+ if ((value & (~0 << 21)) == 0) {
+ return 3;
+ }
+ if ((value & (~0 << 28)) == 0) {
+ return 4;
+ }
+ return 5;
}
/**
@@ -756,7 +702,7 @@ public final class CodedOutputStream {
* {@code sint32} field.
*/
public static int computeSInt32SizeNoTag(final int value) {
- return computeRawVarint32Size(encodeZigZag32(value));
+ return computeUInt32SizeNoTag(encodeZigZag32(value));
}
/**
@@ -764,7 +710,7 @@ public final class CodedOutputStream {
* {@code fixed32} field.
*/
public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
- return LITTLE_ENDIAN_32_SIZE;
+ return FIXED_32_SIZE;
}
/**
@@ -772,7 +718,7 @@ public final class CodedOutputStream {
* {@code sfixed32} field.
*/
public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
- return LITTLE_ENDIAN_32_SIZE;
+ return FIXED_32_SIZE;
}
/**
@@ -780,15 +726,33 @@ public final class CodedOutputStream {
* {@code int64} field, including tag.
*/
public static int computeInt64SizeNoTag(final long value) {
- return computeRawVarint64Size(value);
+ return computeUInt64SizeNoTag(value);
}
/**
* Compute the number of bytes that would be needed to encode a
* {@code uint64} field, including tag.
*/
- public static int computeUInt64SizeNoTag(final long value) {
- return computeRawVarint64Size(value);
+ public static int computeUInt64SizeNoTag(long value) {
+ // handle two popular special cases up front ...
+ if ((value & (~0L << 7)) == 0L) {
+ return 1;
+ }
+ if (value < 0L) {
+ return 10;
+ }
+ // ... leaving us with 8 remaining, which we can divide and conquer
+ int n = 2;
+ if ((value & (~0L << 35)) != 0L) {
+ n += 4; value >>>= 28;
+ }
+ if ((value & (~0L << 21)) != 0L) {
+ n += 2; value >>>= 14;
+ }
+ if ((value & (~0L << 14)) != 0L) {
+ n += 1;
+ }
+ return n;
}
/**
@@ -796,7 +760,7 @@ public final class CodedOutputStream {
* {@code sint64} field.
*/
public static int computeSInt64SizeNoTag(final long value) {
- return computeRawVarint64Size(encodeZigZag64(value));
+ return computeUInt64SizeNoTag(encodeZigZag64(value));
}
/**
@@ -804,7 +768,7 @@ public final class CodedOutputStream {
* {@code fixed64} field.
*/
public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
- return LITTLE_ENDIAN_64_SIZE;
+ return FIXED_64_SIZE;
}
/**
@@ -812,7 +776,7 @@ public final class CodedOutputStream {
* {@code sfixed64} field.
*/
public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
- return LITTLE_ENDIAN_64_SIZE;
+ return FIXED_64_SIZE;
}
/**
@@ -820,7 +784,7 @@ public final class CodedOutputStream {
* {@code float} field, including tag.
*/
public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
- return LITTLE_ENDIAN_32_SIZE;
+ return FIXED_32_SIZE;
}
/**
@@ -828,7 +792,7 @@ public final class CodedOutputStream {
* {@code double} field, including tag.
*/
public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
- return LITTLE_ENDIAN_64_SIZE;
+ return FIXED_64_SIZE;
}
/**
@@ -862,7 +826,7 @@ public final class CodedOutputStream {
length = bytes.length;
}
- return computeRawVarint32Size(length) + length;
+ return computeLengthDelimitedFieldSize(length);
}
/**
@@ -870,8 +834,7 @@ public final class CodedOutputStream {
* message stored in lazy field.
*/
public static int computeLazyFieldSizeNoTag(final LazyFieldLite value) {
- final int size = value.getSerializedSize();
- return computeRawVarint32Size(size) + size;
+ return computeLengthDelimitedFieldSize(value.getSerializedSize());
}
/**
@@ -879,7 +842,7 @@ public final class CodedOutputStream {
* {@code bytes} field.
*/
public static int computeBytesSizeNoTag(final ByteString value) {
- return computeRawVarint32Size(value.size()) + value.size();
+ return computeLengthDelimitedFieldSize(value.size());
}
/**
@@ -887,7 +850,7 @@ public final class CodedOutputStream {
* {@code bytes} field.
*/
public static int computeByteArraySizeNoTag(final byte[] value) {
- return computeRawVarint32Size(value.length) + value.length;
+ return computeLengthDelimitedFieldSize(value.length);
}
/**
@@ -895,7 +858,7 @@ public final class CodedOutputStream {
* {@code bytes} field.
*/
public static int computeByteBufferSizeNoTag(final ByteBuffer value) {
- return computeRawVarint32Size(value.capacity()) + value.capacity();
+ return computeLengthDelimitedFieldSize(value.capacity());
}
/**
@@ -903,8 +866,11 @@ public final class CodedOutputStream {
* message field.
*/
public static int computeMessageSizeNoTag(final MessageLite value) {
- final int size = value.getSerializedSize();
- return computeRawVarint32Size(size) + size;
+ return computeLengthDelimitedFieldSize(value.getSerializedSize());
+ }
+
+ private static int computeLengthDelimitedFieldSize(int fieldLength) {
+ return computeUInt32SizeNoTag(fieldLength) + fieldLength;
}
/**
@@ -943,25 +909,13 @@ public final class CodedOutputStream {
* Flushes the stream and forces any buffered bytes to be written. This
* does not flush the underlying OutputStream.
*/
- public void flush() throws IOException {
- if (output != null) {
- refreshBuffer();
- }
- }
+ public abstract void flush() throws IOException;
/**
* If writing to a flat array, return the space left in the array.
* Otherwise, throws {@code UnsupportedOperationException}.
*/
- public int spaceLeft() {
- if (output == null) {
- return limit - position;
- } else {
- throw new UnsupportedOperationException(
- "spaceLeft() can only be called on CodedOutputStreams that are "
- + "writing to a flat array.");
- }
- }
+ public abstract int spaceLeft();
/**
* Verifies that {@link #spaceLeft()} returns zero. It's common to create
@@ -970,7 +924,7 @@ public final class CodedOutputStream {
* after writing verifies that the message was actually as big as expected,
* which can help catch bugs.
*/
- public void checkNoSpaceLeft() {
+ public final void checkNoSpaceLeft() {
if (spaceLeft() != 0) {
throw new IllegalStateException("Did not write as much data as expected.");
}
@@ -1001,183 +955,31 @@ public final class CodedOutputStream {
* returned value is not guaranteed to be accurate if exceptions have been
* found in the middle of writing.
*/
- public int getTotalBytesWritten() {
- return totalBytesWritten;
- }
+ public abstract int getTotalBytesWritten();
// =================================================================
- /**
- * Internal helper that writes the current buffer to the output. The
- * buffer position is reset to its initial value when this returns.
- */
- private void refreshBuffer() throws IOException {
- if (output == null) {
- // We're writing to a single buffer.
- throw new OutOfSpaceException();
- }
+ /** Write a {@code bytes} field to the stream. Visible for testing. */
+ abstract void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
+ throws IOException;
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- output.write(buffer, 0, position);
- position = 0;
- }
+ final void inefficientWriteStringNoTag(String value, UnpairedSurrogateException cause)
+ throws IOException {
+ logger.log(Level.WARNING,
+ "Converting ill-formed UTF-16. Your Protocol Buffer will not round trip correctly!", cause);
- /** Write a {@code string} field to the stream. */
- private void inefficientWriteStringNoTag(final String value) throws IOException {
// Unfortunately there does not appear to be any way to tell Java to encode
// UTF-8 directly into our buffer, so we have to let it create its own byte
// array and then copy.
// TODO(dweis): Consider using nio Charset methods instead.
final byte[] bytes = value.getBytes(Internal.UTF_8);
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
- }
-
- /**
- * Write a {@code string} field to the stream efficiently. If the {@code string} is malformed,
- * this method rolls back its changes and throws an {@link UnpairedSurrogateException} with the
- * intent that the caller will catch and retry with {@link #inefficientWriteStringNoTag(String)}.
- *
- * @param value the string to write to the stream
- *
- * @throws UnpairedSurrogateException when {@code value} is ill-formed UTF-16.
- */
- private void efficientWriteStringNoTag(final String value) throws IOException {
- // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
- // and at most 3 times of it. We take advantage of this in both branches below.
- final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
- final int maxLengthVarIntSize = computeRawVarint32Size(maxLength);
-
- // If we are streaming and the potential length is too big to fit in our buffer, we take the
- // slower path. Otherwise, we're good to try the fast path.
- if (output != null && maxLengthVarIntSize + maxLength > limit - position) {
- // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
- // does the same internally and then does *another copy* to return a byte[] of exactly the
- // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
- // UTF-8 encoded bytes.
- final byte[] encodedBytes = new byte[maxLength];
- int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
- writeRawVarint32(actualLength);
- writeRawBytes(encodedBytes, 0, actualLength);
- } else {
- // Optimize for the case where we know this length results in a constant varint length as this
- // saves a pass for measuring the length of the string.
- final int minLengthVarIntSize = computeRawVarint32Size(value.length());
- int oldPosition = position;
- final int length;
- try {
- if (minLengthVarIntSize == maxLengthVarIntSize) {
- position = oldPosition + minLengthVarIntSize;
- int newPosition = Utf8.encode(value, buffer, position, limit - position);
- // Since this class is stateful and tracks the position, we rewind and store the state,
- // prepend the length, then reset it back to the end of the string.
- position = oldPosition;
- length = newPosition - oldPosition - minLengthVarIntSize;
- writeRawVarint32(length);
- position = newPosition;
- } else {
- length = Utf8.encodedLength(value);
- writeRawVarint32(length);
- position = Utf8.encode(value, buffer, position, limit - position);
- }
- } catch (UnpairedSurrogateException e) {
- // Be extra careful and restore the original position for retrying the write with the less
- // efficient path.
- position = oldPosition;
- throw e;
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new OutOfSpaceException(e);
- }
- totalBytesWritten += length;
- }
- }
-
- /** Write a ByteBuffer that isn't backed by an array. */
- private void writeRawBytesInternal(final ByteBuffer value) throws IOException {
- int length = value.remaining();
- if (limit - position >= length) {
- // We have room in the current buffer.
- value.get(buffer, position, length);
- position += length;
- totalBytesWritten += length;
- } else {
- // Write extends past current buffer. Fill the rest of this buffer and
- // flush.
- final int bytesWritten = limit - position;
- value.get(buffer, position, bytesWritten);
- length -= bytesWritten;
- position = limit;
- totalBytesWritten += bytesWritten;
- refreshBuffer();
-
- // Now deal with the rest.
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- while (length > limit) {
- // Copy data into the buffer before writing it to OutputStream.
- // TODO(xiaofeng): Introduce ZeroCopyOutputStream to avoid this copy.
- value.get(buffer, 0, limit);
- output.write(buffer, 0, limit);
- length -= limit;
- totalBytesWritten += limit;
- }
- value.get(buffer, 0, length);
- position = length;
- totalBytesWritten += length;
- }
- }
-
- /** Write a {@code bytes} field to the stream. Visible for testing. */
- void writeByteArrayNoTag(final byte[] value, final int offset, final int length)
- throws IOException {
- writeRawVarint32(length);
- writeRawBytes(value, offset, length);
- }
-
- /**
- * Write a {@code bytes} field to the stream. This method will write all
- * content of the ByteBuffer regardless of the current position and limit
- * (i.e., the number of bytes to be written is value.capacity(), not
- * value.remaining()). Furthermore, this method doesn't alter the state of
- * the passed-in ByteBuffer. Its position, limit, mark, etc. will remain
- * unchanged. If you only want to write the remaining bytes of a ByteBuffer,
- * you can call {@code writeByteBufferNoTag(byteBuffer.slice())}.
- */
- private void writeByteBufferNoTag(final ByteBuffer value) throws IOException {
- writeRawVarint32(value.capacity());
- writeRawBytes(value);
- }
-
- /** Write part of a byte string. */
- private void writeRawBytes(final ByteString value, int offset, int length) throws IOException {
- if (limit - position >= length) {
- // We have room in the current buffer.
- value.copyTo(buffer, offset, position, length);
- position += length;
- totalBytesWritten += length;
- } else {
- // Write extends past current buffer. Fill the rest of this buffer and
- // flush.
- final int bytesWritten = limit - position;
- value.copyTo(buffer, offset, position, bytesWritten);
- offset += bytesWritten;
- length -= bytesWritten;
- position = limit;
- totalBytesWritten += bytesWritten;
- refreshBuffer();
-
- // Now deal with the rest.
- // Since we have an output stream, this is our buffer
- // and buffer offset == 0
- if (length <= limit) {
- // Fits in new buffer.
- value.copyTo(buffer, offset, 0, length);
- position = length;
- } else {
- value.writeTo(output, offset, length);
- }
- totalBytesWritten += length;
+ try {
+ writeUInt32NoTag(bytes.length);
+ writeLazy(bytes, 0, bytes.length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ } catch (OutOfSpaceException e) {
+ throw e;
}
}
@@ -1189,7 +991,7 @@ public final class CodedOutputStream {
* @deprecated groups are deprecated.
*/
@Deprecated
- public void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
+ public final void writeGroup(final int fieldNumber, final MessageLite value) throws IOException {
writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
writeGroupNoTag(value);
writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
@@ -1201,7 +1003,7 @@ public final class CodedOutputStream {
* @deprecated groups are deprecated.
*/
@Deprecated
- public void writeGroupNoTag(final MessageLite value) throws IOException {
+ public final void writeGroupNoTag(final MessageLite value) throws IOException {
value.writeTo(this);
}
@@ -1232,16 +1034,8 @@ public final class CodedOutputStream {
* @deprecated use {@link #writeUInt32NoTag} instead.
*/
@Deprecated
- public void writeRawVarint32(int value) throws IOException {
- while (true) {
- if ((value & ~0x7F) == 0) {
- writeRawByte(value);
- return;
- } else {
- writeRawByte((value & 0x7F) | 0x80);
- value >>>= 7;
- }
- }
+ public final void writeRawVarint32(int value) throws IOException {
+ writeUInt32NoTag(value);
}
/**
@@ -1250,16 +1044,8 @@ public final class CodedOutputStream {
* @deprecated use {@link #writeUInt64NoTag} instead.
*/
@Deprecated
- public void writeRawVarint64(long value) throws IOException {
- while (true) {
- if ((value & ~0x7FL) == 0) {
- writeRawByte((int) value);
- return;
- } else {
- writeRawByte(((int) value & 0x7F) | 0x80);
- value >>>= 7;
- }
- }
+ public final void writeRawVarint64(long value) throws IOException {
+ writeUInt64NoTag(value);
}
/**
@@ -1271,19 +1057,7 @@ public final class CodedOutputStream {
*/
@Deprecated
public static int computeRawVarint32Size(final int value) {
- if ((value & (~0 << 7)) == 0) {
- return 1;
- }
- if ((value & (~0 << 14)) == 0) {
- return 2;
- }
- if ((value & (~0 << 21)) == 0) {
- return 3;
- }
- if ((value & (~0 << 28)) == 0) {
- return 4;
- }
- return 5;
+ return computeUInt32SizeNoTag(value);
}
/**
@@ -1293,27 +1067,7 @@ public final class CodedOutputStream {
*/
@Deprecated
public static int computeRawVarint64Size(long value) {
- // handle two popular special cases up front ...
- if ((value & (~0L << 7)) == 0L) {
- return 1;
- }
- if (value < 0L) {
- return 10;
- }
- // ... leaving us with 8 remaining, which we can divide and conquer
- int n = 2;
- if ((value & (~0L << 35)) != 0L) {
- n += 4;
- value >>>= 28;
- }
- if ((value & (~0L << 21)) != 0L) {
- n += 2;
- value >>>= 14;
- }
- if ((value & (~0L << 14)) != 0L) {
- n += 1;
- }
- return n;
+ return computeUInt64SizeNoTag(value);
}
/**
@@ -1322,11 +1076,8 @@ public final class CodedOutputStream {
* @deprecated Use {@link #writeFixed32NoTag} instead.
*/
@Deprecated
- public void writeRawLittleEndian32(final int value) throws IOException {
- writeRawByte((value) & 0xFF);
- writeRawByte((value >> 8) & 0xFF);
- writeRawByte((value >> 16) & 0xFF);
- writeRawByte((value >> 24) & 0xFF);
+ public final void writeRawLittleEndian32(final int value) throws IOException {
+ writeFixed32NoTag(value);
}
/**
@@ -1335,14 +1086,1579 @@ public final class CodedOutputStream {
* @deprecated Use {@link #writeFixed64NoTag} instead.
*/
@Deprecated
- public void writeRawLittleEndian64(final long value) throws IOException {
- writeRawByte((int) (value) & 0xFF);
- writeRawByte((int) (value >> 8) & 0xFF);
- writeRawByte((int) (value >> 16) & 0xFF);
- writeRawByte((int) (value >> 24) & 0xFF);
- writeRawByte((int) (value >> 32) & 0xFF);
- writeRawByte((int) (value >> 40) & 0xFF);
- writeRawByte((int) (value >> 48) & 0xFF);
- writeRawByte((int) (value >> 56) & 0xFF);
+ public final void writeRawLittleEndian64(final long value) throws IOException {
+ writeFixed64NoTag(value);
+ }
+
+ // =================================================================
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a byte array.
+ */
+ private static class ArrayEncoder extends CodedOutputStream {
+ private final byte[] buffer;
+ private final int offset;
+ private final int limit;
+ private int position;
+
+ ArrayEncoder(byte[] buffer, int offset, int length) {
+ if (buffer == null) {
+ throw new NullPointerException("buffer");
+ }
+ if ((offset | length | (buffer.length - (offset + length))) < 0) {
+ throw new IllegalArgumentException(String.format(
+ "Array range is invalid. Buffer.length=%d, offset=%d, length=%d",
+ buffer.length, offset, length));
+ }
+ this.buffer = buffer;
+ this.offset = offset;
+ position = offset;
+ limit = offset + length;
+ }
+
+ @Override
+ public final void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public final void writeInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ @Override
+ public final void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ @Override
+ public final void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ @Override
+ public final void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ @Override
+ public final void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ @Override
+ public final void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public final void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public final void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public final void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public final void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public final void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public final void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public final void writeByteArrayNoTag(final byte[] value, int offset, int length)
+ throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public final void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public final void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public final void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public final void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public final void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public final void write(byte value) throws IOException {
+ try {
+ buffer[position++] = value;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+ }
+ }
+
+ @Override
+ public final void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public final void writeUInt32NoTag(int value) throws IOException {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+ long pos = ARRAY_BASE_OFFSET + position;
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ UNSAFE.putByte(buffer, pos++, (byte) value);
+ position++;
+ return;
+ } else {
+ UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ position++;
+ value >>>= 7;
+ }
+ }
+ } else {
+ try {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer[position++] = (byte) value;
+ return;
+ } else {
+ buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed32NoTag(int value) throws IOException {
+ try {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+ }
+ }
+
+ @Override
+ public final void writeUInt64NoTag(long value) throws IOException {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
+ long pos = ARRAY_BASE_OFFSET + position;
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ UNSAFE.putByte(buffer, pos++, (byte) value);
+ position++;
+ return;
+ } else {
+ UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ position++;
+ value >>>= 7;
+ }
+ }
+ } else {
+ try {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer[position++] = (byte) value;
+ return;
+ } else {
+ buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+ value >>>= 7;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+ }
+ }
+ }
+
+ @Override
+ public final void writeFixed64NoTag(long value) throws IOException {
+ try {
+ buffer[position++] = (byte) ((int) (value) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
+ }
+ }
+
+ @Override
+ public final void write(byte[] value, int offset, int length) throws IOException {
+ try {
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
+ }
+ }
+
+ @Override
+ public final void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public final void write(ByteBuffer value) throws IOException {
+ final int length = value.remaining();
+ try {
+ value.get(buffer, position, length);
+ position += length;
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(
+ new IndexOutOfBoundsException(
+ String.format("Pos: %d, limit: %d, len: %d", position, limit, length)));
+ }
+ }
+
+ @Override
+ public final void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ @Override
+ public final void writeStringNoTag(String value) throws IOException {
+ final int oldPosition = position;
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, spaceLeft());
+ // Since this class is stateful and tracks the position, we rewind and store the state,
+ // prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ int length = newPosition - oldPosition - minLengthVarIntSize;
+ writeUInt32NoTag(length);
+ position = newPosition;
+ } else {
+ int length = Utf8.encodedLength(value);
+ writeUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, spaceLeft());
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change - we fall back to inefficient path.
+ position = oldPosition;
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Do nothing.
+ }
+
+ @Override
+ public final int spaceLeft() {
+ return limit - position;
+ }
+
+ @Override
+ public final int getTotalBytesWritten() {
+ return position - offset;
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffer}. Writes are
+ * done directly to the underlying array. The buffer position is only updated after a flush.
+ */
+ private static final class NioHeapEncoder extends ArrayEncoder {
+ private final ByteBuffer byteBuffer;
+ private int initialPosition;
+
+ NioHeapEncoder(ByteBuffer byteBuffer) {
+ super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(),
+ byteBuffer.remaining());
+ this.byteBuffer = byteBuffer;
+ this.initialPosition = byteBuffer.position();
+ }
+
+ @Override
+ public void flush() {
+ // Update the position on the buffer.
+ byteBuffer.position(initialPosition + getTotalBytesWritten());
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}.
+ */
+ private static final class NioEncoder extends CodedOutputStream {
+ private final ByteBuffer originalBuffer;
+ private final ByteBuffer buffer;
+ private final int initialPosition;
+
+ NioEncoder(ByteBuffer buffer) {
+ this.originalBuffer = buffer;
+ this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
+ initialPosition = buffer.position();
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ writeFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ writeUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ writeFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ write((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ try {
+ buffer.put(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ try {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer.put((byte) value);
+ return;
+ } else {
+ buffer.put((byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeFixed32NoTag(int value) throws IOException {
+ try {
+ buffer.putInt(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ try {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer.put((byte) value);
+ return;
+ } else {
+ buffer.put((byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeFixed64NoTag(long value) throws IOException {
+ try {
+ buffer.putLong(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ try {
+ buffer.put(value, offset, length);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ try {
+ buffer.put(value);
+ } catch (BufferOverflowException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ final int startPos = buffer.position();
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ // Save the current position and increment past the length field. We'll come back
+ // and write the length field after the encoding is complete.
+ final int startOfBytes = buffer.position() + minLengthVarIntSize;
+ buffer.position(startOfBytes);
+
+ // Encode the string.
+ encode(value);
+
+ // Now go back to the beginning and write the length.
+ int endOfBytes = buffer.position();
+ buffer.position(startPos);
+ writeUInt32NoTag(endOfBytes - startOfBytes);
+
+ // Reposition the buffer past the written data.
+ buffer.position(endOfBytes);
+ } else {
+ final int length = Utf8.encodedLength(value);
+ writeUInt32NoTag(length);
+ encode(value);
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change and convert to an IOException.
+ buffer.position(startPos);
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IllegalArgumentException e) {
+ // Thrown by buffer.position() if out of range.
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() {
+ // Update the position of the original buffer.
+ originalBuffer.position(buffer.position());
+ }
+
+ @Override
+ public int spaceLeft() {
+ return buffer.remaining();
+ }
+
+ @Override
+ public int getTotalBytesWritten() {
+ return buffer.position() - initialPosition;
+ }
+
+ private void encode(String value) throws IOException {
+ try {
+ Utf8.encodeUtf8(value, buffer);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+ }
+
+ /**
+ * Abstract base class for buffered encoders.
+ */
+ private abstract static class AbstractBufferedEncoder extends CodedOutputStream {
+ final byte[] buffer;
+ final int limit;
+ int position;
+ int totalBytesWritten;
+
+ AbstractBufferedEncoder(int bufferSize) {
+ if (bufferSize < 0) {
+ throw new IllegalArgumentException("bufferSize must be >= 0");
+ }
+ // As an optimization, we require that the buffer be able to store at least 2
+ // varints so that we can buffer any integer write (tag + value). This reduces the
+ // number of range checks for a single write to 1 (i.e. if there is not enough space
+ // to buffer the tag+value, flush and then buffer it).
+ this.buffer = new byte[max(bufferSize, MAX_VARINT_SIZE * 2)];
+ this.limit = buffer.length;
+ }
+
+ @Override
+ public final int spaceLeft() {
+ throw new UnsupportedOperationException(
+ "spaceLeft() can only be called on CodedOutputStreams that are "
+ + "writing to a flat array or ByteBuffer.");
+ }
+
+ @Override
+ public final int getTotalBytesWritten() {
+ return totalBytesWritten;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void buffer(byte value) {
+ buffer[position++] = value;
+ totalBytesWritten++;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferTag(final int fieldNumber, final int wireType) {
+ bufferUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferInt32NoTag(final int value) {
+ if (value >= 0) {
+ bufferUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ bufferUInt64NoTag(value);
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferUInt32NoTag(int value) {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+ final long originalPos = ARRAY_BASE_OFFSET + position;
+ long pos = originalPos;
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ UNSAFE.putByte(buffer, pos++, (byte) value);
+ break;
+ } else {
+ UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ int delta = (int) (pos - originalPos);
+ position += delta;
+ totalBytesWritten += delta;
+ } else {
+ while (true) {
+ if ((value & ~0x7F) == 0) {
+ buffer[position++] = (byte) value;
+ totalBytesWritten++;
+ return;
+ } else {
+ buffer[position++] = (byte) ((value & 0x7F) | 0x80);
+ totalBytesWritten++;
+ value >>>= 7;
+ }
+ }
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferUInt64NoTag(long value) {
+ if (HAS_UNSAFE_ARRAY_OPERATIONS) {
+ final long originalPos = ARRAY_BASE_OFFSET + position;
+ long pos = originalPos;
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ UNSAFE.putByte(buffer, pos++, (byte) value);
+ break;
+ } else {
+ UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+ value >>>= 7;
+ }
+ }
+ int delta = (int) (pos - originalPos);
+ position += delta;
+ totalBytesWritten += delta;
+ } else {
+ while (true) {
+ if ((value & ~0x7FL) == 0) {
+ buffer[position++] = (byte) value;
+ totalBytesWritten++;
+ return;
+ } else {
+ buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
+ totalBytesWritten++;
+ value >>>= 7;
+ }
+ }
+ }
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferFixed32NoTag(int value) {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ totalBytesWritten += FIXED_32_SIZE;
+ }
+
+ /**
+ * This method does not perform bounds checking on the array. Checking array bounds is the
+ * responsibility of the caller.
+ */
+ final void bufferFixed64NoTag(long value) {
+ buffer[position++] = (byte) (value & 0xFF);
+ buffer[position++] = (byte) ((value >> 8) & 0xFF);
+ buffer[position++] = (byte) ((value >> 16) & 0xFF);
+ buffer[position++] = (byte) ((value >> 24) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
+ buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
+ totalBytesWritten += FIXED_64_SIZE;
+ }
+ }
+
+ /**
+ * A {@link CodedOutputStream} that decorates a {@link ByteOutput}. It internal buffer only to
+ * support string encoding operations. All other writes are just passed through to the
+ * {@link ByteOutput}.
+ */
+ private static final class ByteOutputEncoder extends AbstractBufferedEncoder {
+ private final ByteOutput out;
+
+ ByteOutputEncoder(ByteOutput out, int bufferSize) {
+ super(bufferSize);
+ if (out == null) {
+ throw new NullPointerException("out");
+ }
+ this.out = out;
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ buffer((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ if (position == limit) {
+ doFlush();
+ }
+
+ buffer(value);
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32NoTag(final int value) throws IOException {
+ flushIfNotAvailable(FIXED_32_SIZE);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64NoTag(final long value) throws IOException {
+ flushIfNotAvailable(FIXED_64_SIZE);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+ // If we are streaming and the potential length is too big to fit in our buffer, we take the
+ // slower path.
+ if (maxLengthVarIntSize + maxLength > limit) {
+ // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+ // does the same internally and then does *another copy* to return a byte[] of exactly the
+ // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+ // UTF-8 encoded bytes.
+ final byte[] encodedBytes = new byte[maxLength];
+ int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+ writeUInt32NoTag(actualLength);
+ writeLazy(encodedBytes, 0, actualLength);
+ return;
+ }
+
+ // Fast path: we have enough space available in our buffer for the string...
+ if (maxLengthVarIntSize + maxLength > limit - position) {
+ // Flush to free up space.
+ doFlush();
+ }
+
+ final int oldPosition = position;
+ try {
+ // Optimize for the case where we know this length results in a constant varint length as
+ // this saves a pass for measuring the length of the string.
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, limit - position);
+ // Since this class is stateful and tracks the position, we rewind and store the state,
+ // prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ int length = newPosition - oldPosition - minLengthVarIntSize;
+ bufferUInt32NoTag(length);
+ position = newPosition;
+ totalBytesWritten += length;
+ } else {
+ int length = Utf8.encodedLength(value);
+ bufferUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, length);
+ totalBytesWritten += length;
+ }
+ } catch (UnpairedSurrogateException e) {
+ // Roll back the change and convert to an IOException.
+ totalBytesWritten -= position - oldPosition;
+ position = oldPosition;
+
+ // TODO(nathanmittler): We should throw an IOException here instead.
+ inefficientWriteStringNoTag(value, e);
+ } catch (IndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (position > 0) {
+ // Flush the buffer.
+ doFlush();
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length) throws IOException {
+ flush();
+ out.write(value, offset, length);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ flush();
+ out.writeLazy(value, offset, length);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ flush();
+ int length = value.remaining();
+ out.write(value);
+ totalBytesWritten += length;
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ flush();
+ int length = value.remaining();
+ out.writeLazy(value);
+ totalBytesWritten += length;
+ }
+
+ private void flushIfNotAvailable(int requiredSize) throws IOException {
+ if (limit - position < requiredSize) {
+ doFlush();
+ }
+ }
+
+ private void doFlush() throws IOException {
+ out.write(buffer, 0, position);
+ position = 0;
+ }
+ }
+
+ /**
+ * An {@link CodedOutputStream} that decorates an {@link OutputStream}. It performs internal
+ * buffering to optimize writes to the {@link OutputStream}.
+ */
+ private static final class OutputStreamEncoder extends AbstractBufferedEncoder {
+ private final OutputStream out;
+
+ OutputStreamEncoder(OutputStream out, int bufferSize) {
+ super(bufferSize);
+ if (out == null) {
+ throw new NullPointerException("out");
+ }
+ this.out = out;
+ }
+
+ @Override
+ public void writeTag(final int fieldNumber, final int wireType) throws IOException {
+ writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
+ }
+
+ @Override
+ public void writeInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferInt32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32(final int fieldNumber, final int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE * 2);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64(final int fieldNumber, final long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeBool(final int fieldNumber, final boolean value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE + 1);
+ bufferTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
+ buffer((byte) (value ? 1 : 0));
+ }
+
+ @Override
+ public void writeString(final int fieldNumber, final String value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeStringNoTag(value);
+ }
+
+ @Override
+ public void writeBytes(final int fieldNumber, final ByteString value) throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeBytesNoTag(value);
+ }
+
+ @Override
+ public void writeByteArray(final int fieldNumber, final byte[] value) throws IOException {
+ writeByteArray(fieldNumber, value, 0, value.length);
+ }
+
+ @Override
+ public void writeByteArray(
+ final int fieldNumber, final byte[] value, final int offset, final int length)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeByteArrayNoTag(value, offset, length);
+ }
+
+ @Override
+ public void writeByteBuffer(final int fieldNumber, final ByteBuffer value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeUInt32NoTag(value.capacity());
+ writeRawBytes(value);
+ }
+
+ @Override
+ public void writeBytesNoTag(final ByteString value) throws IOException {
+ writeUInt32NoTag(value.size());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void writeByteArrayNoTag(final byte[] value, int offset, int length) throws IOException {
+ writeUInt32NoTag(length);
+ write(value, offset, length);
+ }
+
+ @Override
+ public void writeRawBytes(final ByteBuffer value) throws IOException {
+ if (value.hasArray()) {
+ write(value.array(), value.arrayOffset(), value.capacity());
+ } else {
+ ByteBuffer duplicated = value.duplicate();
+ duplicated.clear();
+ write(duplicated);
+ }
+ }
+
+ @Override
+ public void writeMessage(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+ writeMessageNoTag(value);
+ }
+
+ @Override
+ public void writeMessageSetExtension(final int fieldNumber, final MessageLite value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeRawMessageSetExtension(final int fieldNumber, final ByteString value)
+ throws IOException {
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
+ writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
+ writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
+ writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
+ }
+
+ @Override
+ public void writeMessageNoTag(final MessageLite value) throws IOException {
+ writeUInt32NoTag(value.getSerializedSize());
+ value.writeTo(this);
+ }
+
+ @Override
+ public void write(byte value) throws IOException {
+ if (position == limit) {
+ doFlush();
+ }
+
+ buffer(value);
+ }
+
+ @Override
+ public void writeInt32NoTag(int value) throws IOException {
+ if (value >= 0) {
+ writeUInt32NoTag(value);
+ } else {
+ // Must sign-extend.
+ writeUInt64NoTag(value);
+ }
+ }
+
+ @Override
+ public void writeUInt32NoTag(int value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt32NoTag(value);
+ }
+
+ @Override
+ public void writeFixed32NoTag(final int value) throws IOException {
+ flushIfNotAvailable(FIXED_32_SIZE);
+ bufferFixed32NoTag(value);
+ }
+
+ @Override
+ public void writeUInt64NoTag(long value) throws IOException {
+ flushIfNotAvailable(MAX_VARINT_SIZE);
+ bufferUInt64NoTag(value);
+ }
+
+ @Override
+ public void writeFixed64NoTag(final long value) throws IOException {
+ flushIfNotAvailable(FIXED_64_SIZE);
+ bufferFixed64NoTag(value);
+ }
+
+ @Override
+ public void writeStringNoTag(String value) throws IOException {
+ try {
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. We take advantage of this in both branches below.
+ final int maxLength = value.length() * Utf8.MAX_BYTES_PER_CHAR;
+ final int maxLengthVarIntSize = computeUInt32SizeNoTag(maxLength);
+
+ // If we are streaming and the potential length is too big to fit in our buffer, we take the
+ // slower path.
+ if (maxLengthVarIntSize + maxLength > limit) {
+ // Allocate a byte[] that we know can fit the string and encode into it. String.getBytes()
+ // does the same internally and then does *another copy* to return a byte[] of exactly the
+ // right size. We can skip that copy and just writeRawBytes up to the actualLength of the
+ // UTF-8 encoded bytes.
+ final byte[] encodedBytes = new byte[maxLength];
+ int actualLength = Utf8.encode(value, encodedBytes, 0, maxLength);
+ writeUInt32NoTag(actualLength);
+ writeLazy(encodedBytes, 0, actualLength);
+ return;
+ }
+
+ // Fast path: we have enough space available in our buffer for the string...
+ if (maxLengthVarIntSize + maxLength > limit - position) {
+ // Flush to free up space.
+ doFlush();
+ }
+
+ // Optimize for the case where we know this length results in a constant varint length as
+ // this saves a pass for measuring the length of the string.
+ final int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
+ int oldPosition = position;
+ final int length;
+ try {
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ position = oldPosition + minLengthVarIntSize;
+ int newPosition = Utf8.encode(value, buffer, position, limit - position);
+ // Since this class is stateful and tracks the position, we rewind and store the
+ // state, prepend the length, then reset it back to the end of the string.
+ position = oldPosition;
+ length = newPosition - oldPosition - minLengthVarIntSize;
+ bufferUInt32NoTag(length);
+ position = newPosition;
+ } else {
+ length = Utf8.encodedLength(value);
+ bufferUInt32NoTag(length);
+ position = Utf8.encode(value, buffer, position, length);
+ }
+ totalBytesWritten += length;
+ } catch (UnpairedSurrogateException e) {
+ // Be extra careful and restore the original position for retrying the write with the
+ // less efficient path.
+ totalBytesWritten -= position - oldPosition;
+ position = oldPosition;
+ throw e;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new OutOfSpaceException(e);
+ }
+ } catch (UnpairedSurrogateException e) {
+ inefficientWriteStringNoTag(value, e);
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (position > 0) {
+ // Flush the buffer.
+ doFlush();
+ }
+ }
+
+ @Override
+ public void write(byte[] value, int offset, int length)
+ throws IOException {
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ System.arraycopy(value, offset, buffer, position, length);
+ position += length;
+ totalBytesWritten += length;
+ } else {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ final int bytesWritten = limit - position;
+ System.arraycopy(value, offset, buffer, position, bytesWritten);
+ offset += bytesWritten;
+ length -= bytesWritten;
+ position = limit;
+ totalBytesWritten += bytesWritten;
+ doFlush();
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ if (length <= limit) {
+ // Fits in new buffer.
+ System.arraycopy(value, offset, buffer, 0, length);
+ position = length;
+ } else {
+ // Write is very big. Let's do it all at once.
+ out.write(value, offset, length);
+ }
+ totalBytesWritten += length;
+ }
+ }
+
+ @Override
+ public void writeLazy(byte[] value, int offset, int length) throws IOException {
+ write(value, offset, length);
+ }
+
+ @Override
+ public void write(ByteBuffer value) throws IOException {
+ int length = value.remaining();
+ if (limit - position >= length) {
+ // We have room in the current buffer.
+ value.get(buffer, position, length);
+ position += length;
+ totalBytesWritten += length;
+ } else {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ final int bytesWritten = limit - position;
+ value.get(buffer, position, bytesWritten);
+ length -= bytesWritten;
+ position = limit;
+ totalBytesWritten += bytesWritten;
+ doFlush();
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ while (length > limit) {
+ // Copy data into the buffer before writing it to OutputStream.
+ value.get(buffer, 0, limit);
+ out.write(buffer, 0, limit);
+ length -= limit;
+ totalBytesWritten += limit;
+ }
+ value.get(buffer, 0, length);
+ position = length;
+ totalBytesWritten += length;
+ }
+ }
+
+ @Override
+ public void writeLazy(ByteBuffer value) throws IOException {
+ write(value);
+ }
+
+ private void flushIfNotAvailable(int requiredSize) throws IOException {
+ if (limit - position < requiredSize) {
+ doFlush();
+ }
+ }
+
+ private void doFlush() throws IOException {
+ out.write(buffer, 0, position);
+ position = 0;
+ }
+ }
+
+ /**
+ * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
+ * platform.
+ */
+ private static sun.misc.Unsafe getUnsafe() {
+ sun.misc.Unsafe unsafe = null;
+ try {
+ unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.misc.Unsafe>() {
+ @Override
+ public sun.misc.Unsafe run() throws Exception {
+ Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
+
+ for (Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x)) {
+ return k.cast(x);
+ }
+ }
+ // The sun.misc.Unsafe field does not exist.
+ return null;
+ }
+ });
+ } catch (Throwable e) {
+ // Catching Throwable here due to the fact that Google AppEngine raises NoClassDefFoundError
+ // for Unsafe.
+ }
+
+ logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
+ unsafe != null ? "available" : "unavailable");
+ return unsafe;
+ }
+
+ /**
+ * Indicates whether or not unsafe array operations are supported on this platform.
+ */
+ // TODO(nathanmittler): Add support for Android's MemoryBlock.
+ private static boolean supportsUnsafeArrayOperations() {
+ boolean supported = false;
+ if (UNSAFE != null) {
+ try {
+ UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class);
+ UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.class);
+ supported = true;
+ } catch (Throwable e) {
+ // Do nothing.
+ }
+ }
+ logger.log(Level.FINEST, "Unsafe array operations: {}",
+ supported ? "available" : "unavailable");
+ return supported;
+ }
+
+ /**
+ * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not
+ * available.
+ */
+ private static <T> int byteArrayBaseOffset() {
+ return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index e303e138..e00ea342 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -74,16 +74,28 @@ public final class Descriptors {
*/
public static final class FileDescriptor extends GenericDescriptor {
/** Convert the descriptor to its protocol message representation. */
- public FileDescriptorProto toProto() { return proto; }
+ @Override
+ public FileDescriptorProto toProto() {
+ return proto;
+ }
/** Get the file name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/** Returns this object. */
- public FileDescriptor getFile() { return this; }
+ @Override
+ public FileDescriptor getFile() {
+ return this;
+ }
/** Returns the same as getName(). */
- public String getFullName() { return proto.getName(); }
+ @Override
+ public String getFullName() {
+ return proto.getName();
+ }
/**
* Get the proto package name. This is the package name given by the
@@ -582,10 +594,16 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public DescriptorProto toProto() { return proto; }
+ @Override
+ public DescriptorProto toProto() {
+ return proto;
+ }
/** Get the type's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/**
* Get the type's fully-qualified name, within the proto language's
@@ -598,10 +616,16 @@ public final class Descriptors {
* </pre>
* {@code Baz}'s full name is "foo.bar.Baz".
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the {@link FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** If this is a nested type, get the outer descriptor, otherwise null. */
public Descriptor getContainingType() { return containingType; }
@@ -875,19 +899,31 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public FieldDescriptorProto toProto() { return proto; }
+ @Override
+ public FieldDescriptorProto toProto() {
+ return proto;
+ }
/** Get the field's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/** Get the field's number. */
- public int getNumber() { return proto.getNumber(); }
+ @Override
+ public int getNumber() {
+ return proto.getNumber();
+ }
/**
* Get the field's fully-qualified name.
* @see Descriptors.Descriptor#getFullName()
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the JSON name of this field. */
public String getJsonName() {
@@ -901,17 +937,22 @@ public final class Descriptors {
public JavaType getJavaType() { return type.getJavaType(); }
/** For internal use only. */
+ @Override
public WireFormat.JavaType getLiteJavaType() {
return getLiteType().getJavaType();
}
/** Get the {@code FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** Get the field's declared type. */
public Type getType() { return type; }
/** For internal use only. */
+ @Override
public WireFormat.FieldType getLiteType() {
return table[type.ordinal()];
}
@@ -953,6 +994,7 @@ public final class Descriptors {
}
/** Is this field declared repeated? */
+ @Override
public boolean isRepeated() {
return proto.getLabel() == FieldDescriptorProto.Label.LABEL_REPEATED;
}
@@ -960,6 +1002,7 @@ public final class Descriptors {
/** Does this field have the {@code [packed = true]} option or is this field
* packable in proto3 and not explicitly setted to unpacked?
*/
+ @Override
public boolean isPacked() {
if (!isPackable()) {
return false;
@@ -1048,6 +1091,7 @@ public final class Descriptors {
}
/** For enum fields, gets the field's type. */
+ @Override
public EnumDescriptor getEnumType() {
if (getJavaType() != JavaType.ENUM) {
throw new UnsupportedOperationException(
@@ -1066,6 +1110,7 @@ public final class Descriptors {
* @return negative, zero, or positive if {@code this} is less than,
* equal to, or greater than {@code other}, respectively.
*/
+ @Override
public int compareTo(final FieldDescriptor other) {
if (other.containingType != containingType) {
throw new IllegalArgumentException(
@@ -1466,8 +1511,8 @@ public final class Descriptors {
* For internal use only. This is to satisfy the FieldDescriptorLite
* interface.
*/
- public MessageLite.Builder internalMergeFrom(
- MessageLite.Builder to, MessageLite from) {
+ @Override
+ public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
// FieldDescriptors are only used with non-lite messages so we can just
// down-cast and call mergeFrom directly.
return ((Message.Builder) to).mergeFrom((Message) from);
@@ -1487,19 +1532,31 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public EnumDescriptorProto toProto() { return proto; }
+ @Override
+ public EnumDescriptorProto toProto() {
+ return proto;
+ }
/** Get the type's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/**
* Get the type's fully-qualified name.
* @see Descriptors.Descriptor#getFullName()
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the {@link FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** If this is a nested type, get the outer descriptor, otherwise null. */
public Descriptor getContainingType() { return containingType; }
@@ -1533,6 +1590,7 @@ public final class Descriptors {
* @param number The value's number.
* @return the value's descriptor, or {@code null} if not found.
*/
+ @Override
public EnumValueDescriptor findValueByNumber(final int number) {
return file.pool.enumValuesByNumber.get(
new DescriptorPool.DescriptorIntPair(this, number));
@@ -1659,13 +1717,22 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public EnumValueDescriptorProto toProto() { return proto; }
+ @Override
+ public EnumValueDescriptorProto toProto() {
+ return proto;
+ }
/** Get the value's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/** Get the value's number. */
- public int getNumber() { return proto.getNumber(); }
+ @Override
+ public int getNumber() {
+ return proto.getNumber();
+ }
@Override
public String toString() { return proto.getName(); }
@@ -1674,10 +1741,16 @@ public final class Descriptors {
* Get the value's fully-qualified name.
* @see Descriptors.Descriptor#getFullName()
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the {@link FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** Get the value's enum type. */
public EnumDescriptor getType() { return type; }
@@ -1745,19 +1818,31 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public ServiceDescriptorProto toProto() { return proto; }
+ @Override
+ public ServiceDescriptorProto toProto() {
+ return proto;
+ }
/** Get the type's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/**
* Get the type's fully-qualified name.
* @see Descriptors.Descriptor#getFullName()
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the {@link FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** Get the {@code ServiceOptions}, defined in {@code descriptor.proto}. */
public ServiceOptions getOptions() { return proto.getOptions(); }
@@ -1835,19 +1920,31 @@ public final class Descriptors {
public int getIndex() { return index; }
/** Convert the descriptor to its protocol message representation. */
- public MethodDescriptorProto toProto() { return proto; }
+ @Override
+ public MethodDescriptorProto toProto() {
+ return proto;
+ }
/** Get the method's unqualified name. */
- public String getName() { return proto.getName(); }
+ @Override
+ public String getName() {
+ return proto.getName();
+ }
/**
* Get the method's fully-qualified name.
* @see Descriptors.Descriptor#getFullName()
*/
- public String getFullName() { return fullName; }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
/** Get the {@link FileDescriptor} containing this descriptor. */
- public FileDescriptor getFile() { return file; }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
/** Get the method's service type. */
public ServiceDescriptor getService() { return service; }
@@ -2248,10 +2345,22 @@ public final class Descriptors {
* that has the same name as an existing package.
*/
private static final class PackageDescriptor extends GenericDescriptor {
- public Message toProto() { return file.toProto(); }
- public String getName() { return name; }
- public String getFullName() { return fullName; }
- public FileDescriptor getFile() { return file; }
+ @Override
+ public Message toProto() {
+ return file.toProto();
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getFullName() {
+ return fullName;
+ }
+ @Override
+ public FileDescriptor getFile() {
+ return file;
+ }
PackageDescriptor(final String name, final String fullName,
final FileDescriptor file) {
diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
index bcc9d6ee..a9543b83 100644
--- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.DoubleList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.RandomAccess;
/**
@@ -45,8 +44,6 @@ import java.util.RandomAccess;
final class DoubleArrayList
extends AbstractProtobufList<Double> implements DoubleList, RandomAccess {
- private static final int DEFAULT_CAPACITY = 10;
-
private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -71,32 +68,56 @@ final class DoubleArrayList
* Constructs a new mutable {@code DoubleArrayList} with default capacity.
*/
DoubleArrayList() {
- this(DEFAULT_CAPACITY);
- }
-
- /**
- * Constructs a new mutable {@code DoubleArrayList} with the provided capacity.
- */
- DoubleArrayList(int capacity) {
- array = new double[capacity];
- size = 0;
+ this(new double[DEFAULT_CAPACITY], 0);
}
/**
* Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}.
*/
- DoubleArrayList(List<Double> other) {
- if (other instanceof DoubleArrayList) {
- DoubleArrayList list = (DoubleArrayList) other;
- array = list.array.clone();
- size = list.size;
- } else {
- size = other.size();
- array = new double[size];
- for (int i = 0; i < size; i++) {
- array[i] = other.get(i);
+ private DoubleArrayList(double[] array, int size) {
+ this.array = array;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof DoubleArrayList)) {
+ return super.equals(o);
+ }
+ DoubleArrayList other = (DoubleArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final double[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
}
}
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ long bits = Double.doubleToLongBits(array[i]);
+ result = (31 * result) + Internal.hashLong(bits);
+ }
+ return result;
+ }
+
+ @Override
+ public DoubleList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new DoubleArrayList(Arrays.copyOf(array, capacity), size);
}
@Override
diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
index 3ea1b688..859a9e8f 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -156,18 +156,22 @@ public final class DynamicMessage extends AbstractMessage {
// -----------------------------------------------------------------
// Implementation of Message interface.
+ @Override
public Descriptor getDescriptorForType() {
return type;
}
+ @Override
public DynamicMessage getDefaultInstanceForType() {
return getDefaultInstance(type);
}
+ @Override
public Map<FieldDescriptor, Object> getAllFields() {
return fields.getAllFields();
}
+ @Override
public boolean hasOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -177,16 +181,19 @@ public final class DynamicMessage extends AbstractMessage {
return true;
}
+ @Override
public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
return oneofCases[oneof.getIndex()];
}
+ @Override
public boolean hasField(FieldDescriptor field) {
verifyContainingType(field);
return fields.hasField(field);
}
+ @Override
public Object getField(FieldDescriptor field) {
verifyContainingType(field);
Object result = fields.getField(field);
@@ -202,16 +209,19 @@ public final class DynamicMessage extends AbstractMessage {
return result;
}
+ @Override
public int getRepeatedFieldCount(FieldDescriptor field) {
verifyContainingType(field);
return fields.getRepeatedFieldCount(field);
}
+ @Override
public Object getRepeatedField(FieldDescriptor field, int index) {
verifyContainingType(field);
return fields.getRepeatedField(field, index);
}
+ @Override
public UnknownFieldSet getUnknownFields() {
return unknownFields;
}
@@ -264,19 +274,22 @@ public final class DynamicMessage extends AbstractMessage {
return size;
}
+ @Override
public Builder newBuilderForType() {
return new Builder(type);
}
+ @Override
public Builder toBuilder() {
return newBuilderForType().mergeFrom(this);
}
+ @Override
public Parser<DynamicMessage> getParserForType() {
return new AbstractParser<DynamicMessage>() {
+ @Override
public DynamicMessage parsePartialFrom(
- CodedInputStream input,
- ExtensionRegistryLite extensionRegistry)
+ CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
Builder builder = newBuilder(type);
try {
@@ -370,6 +383,7 @@ public final class DynamicMessage extends AbstractMessage {
}
}
+ @Override
public DynamicMessage build() {
if (!isInitialized()) {
throw newUninitializedMessageException(
@@ -394,6 +408,7 @@ public final class DynamicMessage extends AbstractMessage {
return buildPartial();
}
+ @Override
public DynamicMessage buildPartial() {
fields.makeImmutable();
DynamicMessage result =
@@ -411,22 +426,27 @@ public final class DynamicMessage extends AbstractMessage {
return result;
}
+ @Override
public boolean isInitialized() {
return DynamicMessage.isInitialized(type, fields);
}
+ @Override
public Descriptor getDescriptorForType() {
return type;
}
+ @Override
public DynamicMessage getDefaultInstanceForType() {
return getDefaultInstance(type);
}
+ @Override
public Map<FieldDescriptor, Object> getAllFields() {
return fields.getAllFields();
}
+ @Override
public Builder newBuilderForField(FieldDescriptor field) {
verifyContainingType(field);
@@ -438,6 +458,7 @@ public final class DynamicMessage extends AbstractMessage {
return new Builder(field.getMessageType());
}
+ @Override
public boolean hasOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -447,11 +468,13 @@ public final class DynamicMessage extends AbstractMessage {
return true;
}
+ @Override
public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
return oneofCases[oneof.getIndex()];
}
+ @Override
public Builder clearOneof(OneofDescriptor oneof) {
verifyOneofContainingType(oneof);
FieldDescriptor field = oneofCases[oneof.getIndex()];
@@ -461,11 +484,13 @@ public final class DynamicMessage extends AbstractMessage {
return this;
}
+ @Override
public boolean hasField(FieldDescriptor field) {
verifyContainingType(field);
return fields.hasField(field);
}
+ @Override
public Object getField(FieldDescriptor field) {
verifyContainingType(field);
Object result = fields.getField(field);
@@ -481,6 +506,7 @@ public final class DynamicMessage extends AbstractMessage {
return result;
}
+ @Override
public Builder setField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
@@ -505,6 +531,7 @@ public final class DynamicMessage extends AbstractMessage {
return this;
}
+ @Override
public Builder clearField(FieldDescriptor field) {
verifyContainingType(field);
ensureIsMutable();
@@ -519,24 +546,27 @@ public final class DynamicMessage extends AbstractMessage {
return this;
}
+ @Override
public int getRepeatedFieldCount(FieldDescriptor field) {
verifyContainingType(field);
return fields.getRepeatedFieldCount(field);
}
+ @Override
public Object getRepeatedField(FieldDescriptor field, int index) {
verifyContainingType(field);
return fields.getRepeatedField(field, index);
}
- public Builder setRepeatedField(FieldDescriptor field,
- int index, Object value) {
+ @Override
+ public Builder setRepeatedField(FieldDescriptor field, int index, Object value) {
verifyContainingType(field);
ensureIsMutable();
fields.setRepeatedField(field, index, value);
return this;
}
+ @Override
public Builder addRepeatedField(FieldDescriptor field, Object value) {
verifyContainingType(field);
ensureIsMutable();
@@ -544,10 +574,12 @@ public final class DynamicMessage extends AbstractMessage {
return this;
}
+ @Override
public UnknownFieldSet getUnknownFields() {
return unknownFields;
}
+ @Override
public Builder setUnknownFields(UnknownFieldSet unknownFields) {
if (getDescriptorForType().getFile().getSyntax()
== Descriptors.FileDescriptor.Syntax.PROTO3) {
diff --git a/java/core/src/main/java/com/google/protobuf/Extension.java b/java/core/src/main/java/com/google/protobuf/Extension.java
index 68d29f33..08ec5b45 100644
--- a/java/core/src/main/java/com/google/protobuf/Extension.java
+++ b/java/core/src/main/java/com/google/protobuf/Extension.java
@@ -42,6 +42,7 @@ public abstract class Extension<ContainingType extends MessageLite, Type>
public abstract Descriptors.FieldDescriptor getDescriptor();
/** Returns whether or not this extension is a Lite Extension. */
+ @Override
final boolean isLite() {
return false;
}
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 47924b65..4e89709f 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -120,6 +120,25 @@ final class FieldSet<FieldDescriptorType extends
public boolean isImmutable() {
return isImmutable;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof FieldSet)) {
+ return false;
+ }
+
+ FieldSet<?> other = (FieldSet<?>) o;
+ return other.fields.equals(other.fields);
+ }
+
+ @Override
+ public int hashCode() {
+ return fields.hashCode();
+ }
/**
* Clones the FieldSet. The returned FieldSet will be mutable even if the
diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
index 033b5eed..63cb6d77 100644
--- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.FloatList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.RandomAccess;
/**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
*/
final class FloatArrayList extends AbstractProtobufList<Float> implements FloatList, RandomAccess {
- private static final int DEFAULT_CAPACITY = 10;
-
private static final FloatArrayList EMPTY_LIST = new FloatArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class FloatArrayList extends AbstractProtobufList<Float> implements FloatL
* Constructs a new mutable {@code FloatArrayList} with default capacity.
*/
FloatArrayList() {
- this(DEFAULT_CAPACITY);
- }
-
- /**
- * Constructs a new mutable {@code FloatArrayList} with the provided capacity.
- */
- FloatArrayList(int capacity) {
- array = new float[capacity];
- size = 0;
+ this(new float[DEFAULT_CAPACITY], 0);
}
/**
* Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}.
*/
- FloatArrayList(List<Float> other) {
- if (other instanceof FloatArrayList) {
- FloatArrayList list = (FloatArrayList) other;
- array = list.array.clone();
- size = list.size;
- } else {
- size = other.size();
- array = new float[size];
- for (int i = 0; i < size; i++) {
- array[i] = other.get(i);
+ private FloatArrayList(float[] array, int size) {
+ this.array = array;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof FloatArrayList)) {
+ return super.equals(o);
+ }
+ FloatArrayList other = (FloatArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final float[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
}
}
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Float.floatToIntBits(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public FloatList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new FloatArrayList(Arrays.copyOf(array, capacity), size);
}
@Override
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
index a50afe55..57e732a0 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -80,6 +80,7 @@ public abstract class GeneratedMessage extends AbstractMessage
unknownFields = builder.getUnknownFields();
}
+ @Override
public Parser<? extends GeneratedMessage> getParserForType() {
throw new UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
@@ -102,7 +103,7 @@ public abstract class GeneratedMessage extends AbstractMessage
*/
protected abstract FieldAccessorTable internalGetFieldAccessorTable();
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Descriptor getDescriptorForType() {
return internalGetFieldAccessorTable().descriptor;
}
@@ -191,7 +192,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return true;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Map<FieldDescriptor, Object> getAllFields() {
return Collections.unmodifiableMap(
getAllFieldsMutable(/* getBytesForString = */ false));
@@ -212,22 +213,22 @@ public abstract class GeneratedMessage extends AbstractMessage
getAllFieldsMutable(/* getBytesForString = */ true));
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasOneof(final OneofDescriptor oneof) {
return internalGetFieldAccessorTable().getOneof(oneof).has(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
return internalGetFieldAccessorTable().getOneof(oneof).get(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).has(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Object getField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).get(this);
}
@@ -244,19 +245,19 @@ public abstract class GeneratedMessage extends AbstractMessage
return internalGetFieldAccessorTable().getField(field).getRaw(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public int getRepeatedFieldCount(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field)
.getRepeatedCount(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Object getRepeatedField(final FieldDescriptor field, final int index) {
return internalGetFieldAccessorTable().getField(field)
.getRepeated(this, index);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public UnknownFieldSet getUnknownFields() {
throw new UnsupportedOperationException(
"This is supposed to be overridden by subclasses.");
@@ -380,7 +381,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
@SuppressWarnings("unchecked")
- public abstract static class Builder <BuilderType extends Builder>
+ public abstract static class Builder <BuilderType extends Builder<BuilderType>>
extends AbstractMessage.Builder<BuilderType> {
private BuilderParent builderParent;
@@ -444,6 +445,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* Called by the initialization and clear code paths to allow subclasses to
* reset any of their builtin fields back to the initial values.
*/
+ @Override
public BuilderType clear() {
unknownFields = UnknownFieldSet.getDefaultInstance();
onChanged();
@@ -457,12 +459,12 @@ public abstract class GeneratedMessage extends AbstractMessage
*/
protected abstract FieldAccessorTable internalGetFieldAccessorTable();
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Descriptor getDescriptorForType() {
return internalGetFieldAccessorTable().descriptor;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Map<FieldDescriptor, Object> getAllFields() {
return Collections.unmodifiableMap(getAllFieldsMutable());
}
@@ -510,39 +512,38 @@ public abstract class GeneratedMessage extends AbstractMessage
return result;
}
- public Message.Builder newBuilderForField(
- final FieldDescriptor field) {
+ @Override
+ public Message.Builder newBuilderForField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).newBuilder();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Message.Builder getFieldBuilder(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).getBuilder(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field,
- int index) {
+ @Override
+ public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
this, index);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasOneof(final OneofDescriptor oneof) {
return internalGetFieldAccessorTable().getOneof(oneof).has(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public FieldDescriptor getOneofFieldDescriptor(final OneofDescriptor oneof) {
return internalGetFieldAccessorTable().getOneof(oneof).get(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasField(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field).has(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Object getField(final FieldDescriptor field) {
Object object = internalGetFieldAccessorTable().getField(field).get(this);
if (field.isRepeated()) {
@@ -554,52 +555,52 @@ public abstract class GeneratedMessage extends AbstractMessage
}
}
- public BuilderType setField(final FieldDescriptor field,
- final Object value) {
+ @Override
+ public BuilderType setField(final FieldDescriptor field, final Object value) {
internalGetFieldAccessorTable().getField(field).set(this, value);
return (BuilderType) this;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public BuilderType clearField(final FieldDescriptor field) {
internalGetFieldAccessorTable().getField(field).clear(this);
return (BuilderType) this;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public BuilderType clearOneof(final OneofDescriptor oneof) {
internalGetFieldAccessorTable().getOneof(oneof).clear(this);
return (BuilderType) this;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public int getRepeatedFieldCount(final FieldDescriptor field) {
return internalGetFieldAccessorTable().getField(field)
.getRepeatedCount(this);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public Object getRepeatedField(final FieldDescriptor field,
- final int index) {
+ @Override
+ public Object getRepeatedField(final FieldDescriptor field, final int index) {
return internalGetFieldAccessorTable().getField(field)
.getRepeated(this, index);
}
- public BuilderType setRepeatedField(final FieldDescriptor field,
- final int index, final Object value) {
+ @Override
+ public BuilderType setRepeatedField(
+ final FieldDescriptor field, final int index, final Object value) {
internalGetFieldAccessorTable().getField(field)
.setRepeated(this, index, value);
return (BuilderType) this;
}
- public BuilderType addRepeatedField(final FieldDescriptor field,
- final Object value) {
+ @Override
+ public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
return (BuilderType) this;
}
- public BuilderType setUnknownFields(
- final UnknownFieldSet unknownFields) {
+ @Override
+ public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
this.unknownFields = unknownFields;
onChanged();
return (BuilderType) this;
@@ -616,7 +617,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return (BuilderType) this;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean isInitialized() {
for (final FieldDescriptor field : getDescriptorForType().getFields()) {
// Check that all required fields are present.
@@ -646,7 +647,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return true;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final UnknownFieldSet getUnknownFields() {
return unknownFields;
}
@@ -670,7 +671,7 @@ public abstract class GeneratedMessage extends AbstractMessage
*/
private class BuilderParentImpl implements BuilderParent {
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void markDirty() {
onChanged();
}
@@ -735,6 +736,7 @@ public abstract class GeneratedMessage extends AbstractMessage
public interface ExtendableMessageOrBuilder<
MessageType extends ExtendableMessage> extends MessageOrBuilder {
// Re-define for return type covariance.
+ @Override
Message getDefaultInstanceForType();
/** Check if a singular extension is present. */
@@ -821,9 +823,8 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Check if a singular extension is present. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public final <Type> boolean hasExtension(
- final ExtensionLite<MessageType, Type> extensionLite) {
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -831,7 +832,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get the number of elements in a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final <Type> int getExtensionCount(
final ExtensionLite<MessageType, List<Type>> extensionLite) {
Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
@@ -842,10 +843,9 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get the value of an extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
@SuppressWarnings("unchecked")
- public final <Type> Type getExtension(
- final ExtensionLite<MessageType, Type> extensionLite) {
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -867,11 +867,10 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get one element of a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final ExtensionLite<MessageType, List<Type>> extensionLite,
- final int index) {
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -1105,7 +1104,7 @@ public abstract class GeneratedMessage extends AbstractMessage
@SuppressWarnings("unchecked")
public abstract static class ExtendableBuilder<
MessageType extends ExtendableMessage,
- BuilderType extends ExtendableBuilder>
+ BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
extends Builder<BuilderType>
implements ExtendableMessageOrBuilder<MessageType> {
@@ -1157,9 +1156,8 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Check if a singular extension is present. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public final <Type> boolean hasExtension(
- final ExtensionLite<MessageType, Type> extensionLite) {
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -1167,7 +1165,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get the number of elements in a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final <Type> int getExtensionCount(
final ExtensionLite<MessageType, List<Type>> extensionLite) {
Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
@@ -1178,9 +1176,8 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get the value of an extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public final <Type> Type getExtension(
- final ExtensionLite<MessageType, Type> extensionLite) {
+ @Override
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
Extension<MessageType, Type> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -1202,10 +1199,9 @@ public abstract class GeneratedMessage extends AbstractMessage
}
/** Get one element of a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final <Type> Type getExtension(
- final ExtensionLite<MessageType, List<Type>> extensionLite,
- final int index) {
+ final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
verifyExtensionContainingType(extension);
@@ -1458,10 +1454,9 @@ public abstract class GeneratedMessage extends AbstractMessage
// obtained.
return new GeneratedExtension<ContainingType, Type>(
new CachedDescriptorRetriever() {
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public FieldDescriptor loadDescriptor() {
- return scope.getDescriptorForType().getExtensions()
- .get(descriptorIndex);
+ return scope.getDescriptorForType().getExtensions().get(descriptorIndex);
}
},
singularType,
@@ -1489,6 +1484,7 @@ public abstract class GeneratedMessage extends AbstractMessage
private volatile FieldDescriptor descriptor;
protected abstract FieldDescriptor loadDescriptor();
+ @Override
public FieldDescriptor getDescriptor() {
if (descriptor == null) {
synchronized (this) {
@@ -1518,6 +1514,7 @@ public abstract class GeneratedMessage extends AbstractMessage
// obtained.
return new GeneratedExtension<ContainingType, Type>(
new CachedDescriptorRetriever() {
+ @Override
protected FieldDescriptor loadDescriptor() {
return scope.getDescriptorForType().findFieldByName(name);
}
@@ -1544,17 +1541,18 @@ public abstract class GeneratedMessage extends AbstractMessage
// used to obtain the extension's FieldDescriptor.
return new GeneratedExtension<ContainingType, Type>(
new CachedDescriptorRetriever() {
+ @Override
protected FieldDescriptor loadDescriptor() {
try {
- Class clazz =
- singularType.getClassLoader().loadClass(descriptorOuterClass);
- FileDescriptor file =
- (FileDescriptor) clazz.getField("descriptor").get(null);
+ Class clazz = singularType.getClassLoader().loadClass(descriptorOuterClass);
+ FileDescriptor file = (FileDescriptor) clazz.getField("descriptor").get(null);
return file.findExtensionByName(extensionName);
} catch (Exception e) {
throw new RuntimeException(
- "Cannot load descriptors: " + descriptorOuterClass +
- " is not a valid descriptor class name", e);
+ "Cannot load descriptors: "
+ + descriptorOuterClass
+ + " is not a valid descriptor class name",
+ e);
}
}
},
@@ -1636,12 +1634,13 @@ public abstract class GeneratedMessage extends AbstractMessage
if (descriptorRetriever != null) {
throw new IllegalStateException("Already initialized.");
}
- descriptorRetriever = new ExtensionDescriptorRetriever() {
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public FieldDescriptor getDescriptor() {
- return descriptor;
- }
- };
+ descriptorRetriever =
+ new ExtensionDescriptorRetriever() {
+ @Override
+ public FieldDescriptor getDescriptor() {
+ return descriptor;
+ }
+ };
}
private ExtensionDescriptorRetriever descriptorRetriever;
@@ -1651,6 +1650,7 @@ public abstract class GeneratedMessage extends AbstractMessage
private final Method enumGetValueDescriptor;
private final ExtensionType extensionType;
+ @Override
public FieldDescriptor getDescriptor() {
if (descriptorRetriever == null) {
throw new IllegalStateException(
@@ -1663,10 +1663,12 @@ public abstract class GeneratedMessage extends AbstractMessage
* If the extension is an embedded message or group, returns the default
* instance of the message.
*/
+ @Override
public Message getMessageDefaultInstance() {
return messageDefaultInstance;
}
+ @Override
protected ExtensionType getExtensionType() {
return extensionType;
}
@@ -1677,7 +1679,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* EnumValueDescriptors but the native accessors use the generated enum
* type.
*/
- // @Override
+ @Override
@SuppressWarnings("unchecked")
protected Object fromReflectionType(final Object value) {
FieldDescriptor descriptor = getDescriptor();
@@ -1702,7 +1704,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* Like {@link #fromReflectionType(Object)}, but if the type is a repeated
* type, this converts a single element.
*/
- // @Override
+ @Override
protected Object singularFromReflectionType(final Object value) {
FieldDescriptor descriptor = getDescriptor();
switch (descriptor.getJavaType()) {
@@ -1726,7 +1728,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* EnumValueDescriptors but the native accessors use the generated enum
* type.
*/
- // @Override
+ @Override
@SuppressWarnings("unchecked")
protected Object toReflectionType(final Object value) {
FieldDescriptor descriptor = getDescriptor();
@@ -1750,7 +1752,7 @@ public abstract class GeneratedMessage extends AbstractMessage
* Like {@link #toReflectionType(Object)}, but if the type is a repeated
* type, this converts a single element.
*/
- // @Override
+ @Override
protected Object singularToReflectionType(final Object value) {
FieldDescriptor descriptor = getDescriptor();
switch (descriptor.getJavaType()) {
@@ -1761,22 +1763,22 @@ public abstract class GeneratedMessage extends AbstractMessage
}
}
- // @Override
+ @Override
public int getNumber() {
return getDescriptor().getNumber();
}
- // @Override
+ @Override
public WireFormat.FieldType getLiteType() {
return getDescriptor().getLiteType();
}
- // @Override
+ @Override
public boolean isRepeated() {
return getDescriptor().isRepeated();
}
- // @Override
+ @Override
@SuppressWarnings("unchecked")
public Type getDefaultValue() {
if (isRepeated()) {
@@ -2126,49 +2128,57 @@ public abstract class GeneratedMessage extends AbstractMessage
return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber();
}
+ @Override
public Object get(final GeneratedMessage message) {
return invokeOrDie(getMethod, message);
}
+ @Override
public Object get(GeneratedMessage.Builder builder) {
return invokeOrDie(getMethodBuilder, builder);
}
+ @Override
public Object getRaw(final GeneratedMessage message) {
return get(message);
}
+ @Override
public Object getRaw(GeneratedMessage.Builder builder) {
return get(builder);
}
+ @Override
public void set(final Builder builder, final Object value) {
invokeOrDie(setMethod, builder, value);
}
- public Object getRepeated(final GeneratedMessage message,
- final int index) {
+ @Override
+ public Object getRepeated(final GeneratedMessage message, final int index) {
throw new UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
- public Object getRepeatedRaw(final GeneratedMessage message,
- final int index) {
+ @Override
+ public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
throw new UnsupportedOperationException(
"getRepeatedFieldRaw() called on a singular field.");
}
+ @Override
public Object getRepeated(GeneratedMessage.Builder builder, int index) {
throw new UnsupportedOperationException(
"getRepeatedField() called on a singular field.");
}
- public Object getRepeatedRaw(GeneratedMessage.Builder builder,
- int index) {
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
throw new UnsupportedOperationException(
"getRepeatedFieldRaw() called on a singular field.");
}
- public void setRepeated(final Builder builder, final int index,
- final Object value) {
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
throw new UnsupportedOperationException(
"setRepeatedField() called on a singular field.");
}
+ @Override
public void addRepeated(final Builder builder, final Object value) {
throw new UnsupportedOperationException(
"addRepeatedField() called on a singular field.");
}
+ @Override
public boolean has(final GeneratedMessage message) {
if (!hasHasMethod) {
if (isOneofField) {
@@ -2178,6 +2188,7 @@ public abstract class GeneratedMessage extends AbstractMessage
}
return (Boolean) invokeOrDie(hasMethod, message);
}
+ @Override
public boolean has(GeneratedMessage.Builder builder) {
if (!hasHasMethod) {
if (isOneofField) {
@@ -2187,27 +2198,32 @@ public abstract class GeneratedMessage extends AbstractMessage
}
return (Boolean) invokeOrDie(hasMethodBuilder, builder);
}
+ @Override
public int getRepeatedCount(final GeneratedMessage message) {
throw new UnsupportedOperationException(
"getRepeatedFieldSize() called on a singular field.");
}
+ @Override
public int getRepeatedCount(GeneratedMessage.Builder builder) {
throw new UnsupportedOperationException(
"getRepeatedFieldSize() called on a singular field.");
}
+ @Override
public void clear(final Builder builder) {
invokeOrDie(clearMethod, builder);
}
+ @Override
public Message.Builder newBuilder() {
throw new UnsupportedOperationException(
"newBuilderForField() called on a non-Message type.");
}
+ @Override
public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
throw new UnsupportedOperationException(
"getFieldBuilder() called on a non-Message type.");
}
- public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
- int index) {
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on a non-Message type.");
}
@@ -2251,18 +2267,23 @@ public abstract class GeneratedMessage extends AbstractMessage
clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
}
+ @Override
public Object get(final GeneratedMessage message) {
return invokeOrDie(getMethod, message);
}
+ @Override
public Object get(GeneratedMessage.Builder builder) {
return invokeOrDie(getMethodBuilder, builder);
}
+ @Override
public Object getRaw(final GeneratedMessage message) {
return get(message);
}
+ @Override
public Object getRaw(GeneratedMessage.Builder builder) {
return get(builder);
}
+ @Override
public void set(final Builder builder, final Object value) {
// Add all the elements individually. This serves two purposes:
// 1) Verifies that each element has the correct type.
@@ -2273,54 +2294,64 @@ public abstract class GeneratedMessage extends AbstractMessage
addRepeated(builder, element);
}
}
- public Object getRepeated(final GeneratedMessage message,
- final int index) {
+ @Override
+ public Object getRepeated(final GeneratedMessage message, final int index) {
return invokeOrDie(getRepeatedMethod, message, index);
}
+ @Override
public Object getRepeated(GeneratedMessage.Builder builder, int index) {
return invokeOrDie(getRepeatedMethodBuilder, builder, index);
}
+ @Override
public Object getRepeatedRaw(GeneratedMessage message, int index) {
return getRepeated(message, index);
}
- public Object getRepeatedRaw(GeneratedMessage.Builder builder,
- int index) {
+ @Override
+ public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
return getRepeated(builder, index);
}
- public void setRepeated(final Builder builder,
- final int index, final Object value) {
+ @Override
+ public void setRepeated(final Builder builder, final int index, final Object value) {
invokeOrDie(setRepeatedMethod, builder, index, value);
}
+ @Override
public void addRepeated(final Builder builder, final Object value) {
invokeOrDie(addRepeatedMethod, builder, value);
}
+ @Override
public boolean has(final GeneratedMessage message) {
throw new UnsupportedOperationException(
"hasField() called on a repeated field.");
}
+ @Override
public boolean has(GeneratedMessage.Builder builder) {
throw new UnsupportedOperationException(
"hasField() called on a repeated field.");
}
+ @Override
public int getRepeatedCount(final GeneratedMessage message) {
return (Integer) invokeOrDie(getCountMethod, message);
}
+ @Override
public int getRepeatedCount(GeneratedMessage.Builder builder) {
return (Integer) invokeOrDie(getCountMethodBuilder, builder);
}
+ @Override
public void clear(final Builder builder) {
invokeOrDie(clearMethod, builder);
}
+ @Override
public Message.Builder newBuilder() {
throw new UnsupportedOperationException(
"newBuilderForField() called on a non-Message type.");
}
+ @Override
public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
throw new UnsupportedOperationException(
"getFieldBuilder() called on a non-Message type.");
}
- public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
- int index) {
+ @Override
+ public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
throw new UnsupportedOperationException(
"getRepeatedFieldBuilder() called on a non-Message type.");
}
@@ -2357,6 +2388,7 @@ public abstract class GeneratedMessage extends AbstractMessage
field.getNumber());
}
+ @Override
public Object get(GeneratedMessage message) {
List result = new ArrayList();
for (int i = 0; i < getRepeatedCount(message); i++) {
@@ -2365,6 +2397,7 @@ public abstract class GeneratedMessage extends AbstractMessage
return Collections.unmodifiableList(result);
}
+ @Override
public Object get(Builder builder) {
List result = new ArrayList();
for (int i = 0; i < getRepeatedCount(builder); i++) {
@@ -2373,14 +2406,17 @@ public abstract class GeneratedMessage extends AbstractMessage
return Collections.unmodifiableList(result);
}
+ @Override
public Object getRaw(GeneratedMessage message) {
return get(message);
}
+ @Override
public Object getRaw(GeneratedMessage.Builder builder) {
return get(builder);
}
+ @Override
public void set(Builder builder, Object value) {
clear(builder);
for (Object entry : (List) value) {
@@ -2388,63 +2424,76 @@ public abstract class GeneratedMessage extends AbstractMessage
}
}
+ @Override
public Object getRepeated(GeneratedMessage message, int index) {
return getMapField(message).getList().get(index);
}
+ @Override
public Object getRepeated(Builder builder, int index) {
return getMapField(builder).getList().get(index);
}
+ @Override
public Object getRepeatedRaw(GeneratedMessage message, int index) {
return getRepeated(message, index);
}
+ @Override
public Object getRepeatedRaw(Builder builder, int index) {
return getRepeated(builder, index);
}
+ @Override
public void setRepeated(Builder builder, int index, Object value) {
getMutableMapField(builder).getMutableList().set(index, (Message) value);
}
+ @Override
public void addRepeated(Builder builder, Object value) {
getMutableMapField(builder).getMutableList().add((Message) value);
}
+ @Override
public boolean has(GeneratedMessage message) {
throw new UnsupportedOperationException(
"hasField() is not supported for repeated fields.");
}
+ @Override
public boolean has(Builder builder) {
throw new UnsupportedOperationException(
"hasField() is not supported for repeated fields.");
}
+ @Override
public int getRepeatedCount(GeneratedMessage message) {
return getMapField(message).getList().size();
}
+ @Override
public int getRepeatedCount(Builder builder) {
return getMapField(builder).getList().size();
}
+ @Override
public void clear(Builder builder) {
getMutableMapField(builder).getMutableList().clear();
}
+ @Override
public com.google.protobuf.Message.Builder newBuilder() {
return mapEntryMessageDefaultInstance.newBuilderForType();
}
+ @Override
public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
throw new UnsupportedOperationException(
"Nested builder not supported for map fields.");
}
- public com.google.protobuf.Message.Builder getRepeatedBuilder(
- Builder builder, int index) {
+ @Override
+ public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
throw new UnsupportedOperationException(
"Nested builder not supported for map fields.");
}
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 12a1472d..c5adc5ad 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -31,6 +31,7 @@
package com.google.protobuf;
import com.google.protobuf.AbstractMessageLite.Builder.LimitedInputStream;
+import com.google.protobuf.GeneratedMessageLite.EqualsVisitor.NotEqualsException;
import com.google.protobuf.Internal.BooleanList;
import com.google.protobuf.Internal.DoubleList;
import com.google.protobuf.Internal.FloatList;
@@ -59,24 +60,27 @@ import java.util.Map;
public abstract class GeneratedMessageLite<
MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
BuilderType extends GeneratedMessageLite.Builder<MessageType, BuilderType>>
- extends AbstractMessageLite {
+ extends AbstractMessageLite<MessageType, BuilderType> {
/** For use by generated code only. Lazily initialized to reduce allocations. */
- protected UnknownFieldSetLite unknownFields = null;
+ protected UnknownFieldSetLite unknownFields = UnknownFieldSetLite.getDefaultInstance();
/** For use by generated code only. */
protected int memoizedSerializedSize = -1;
+ @Override
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final Parser<MessageType> getParserForType() {
return (Parser<MessageType>) dynamicMethod(MethodToInvoke.GET_PARSER);
}
+ @Override
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final MessageType getDefaultInstanceForType() {
return (MessageType) dynamicMethod(MethodToInvoke.GET_DEFAULT_INSTANCE);
}
+ @Override
@SuppressWarnings("unchecked") // Guaranteed by runtime.
public final BuilderType newBuilderForType() {
return (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
@@ -99,7 +103,65 @@ public abstract class GeneratedMessageLite<
return MessageLiteToString.toString(this, super.toString());
}
+ @SuppressWarnings("unchecked") // Guaranteed by runtime
+ @Override
+ public int hashCode() {
+ if (memoizedHashCode == 0) {
+ HashCodeVisitor visitor = new HashCodeVisitor();
+ visit(visitor, (MessageType) this);
+ memoizedHashCode = visitor.hashCode;
+ }
+ return memoizedHashCode;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by runtime
+ int hashCode(HashCodeVisitor visitor) {
+ if (memoizedHashCode == 0) {
+ int inProgressHashCode = visitor.hashCode;
+ visitor.hashCode = 0;
+ visit(visitor, (MessageType) this);
+ memoizedHashCode = visitor.hashCode;
+ visitor.hashCode = inProgressHashCode;
+ }
+ return memoizedHashCode;
+ }
+
+ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ return false;
+ }
+
+ try {
+ visit(EqualsVisitor.INSTANCE, (MessageType) other);
+ } catch (NotEqualsException e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Same as {@link #equals(Object)} but throws {@code NotEqualsException}.
+ */
+ @SuppressWarnings("unchecked") // Guaranteed by isInstance + runtime
+ boolean equals(EqualsVisitor visitor, MessageLite other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!getDefaultInstanceForType().getClass().isInstance(other)) {
+ return false;
+ }
+ visit(visitor, (MessageType) other);
+ return true;
+ }
+
// The general strategy for unknown fields is to use an UnknownFieldSetLite that is treated as
// mutable during the parsing constructor and immutable after. This allows us to avoid
// any unnecessary intermediary allocations while reducing the generated code size.
@@ -108,7 +170,7 @@ public abstract class GeneratedMessageLite<
* Lazily initializes unknown fields.
*/
private final void ensureUnknownFieldsInitialized() {
- if (unknownFields == null) {
+ if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
unknownFields = UnknownFieldSetLite.newInstance();
}
}
@@ -147,18 +209,18 @@ public abstract class GeneratedMessageLite<
/**
* Called by subclasses to complete parsing. For use by generated code only.
*/
- protected void doneParsing() {
- if (unknownFields == null) {
- unknownFields = UnknownFieldSetLite.getDefaultInstance();
- } else {
- unknownFields.makeImmutable();
- }
+ protected void makeImmutable() {
+ dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
+
+ unknownFields.makeImmutable();
}
+ @Override
public final boolean isInitialized() {
return dynamicMethod(MethodToInvoke.IS_INITIALIZED, Boolean.TRUE) != null;
}
+ @Override
public final BuilderType toBuilder() {
BuilderType builder = (BuilderType) dynamicMethod(MethodToInvoke.NEW_BUILDER);
builder.mergeFrom((MessageType) this);
@@ -172,11 +234,14 @@ public abstract class GeneratedMessageLite<
* For use by generated code only.
*/
public static enum MethodToInvoke {
+ // Rely on/modify instance state
IS_INITIALIZED,
- PARSE_PARTIAL_FROM,
- MERGE_FROM,
+ VISIT,
+ MERGE_FROM_STREAM,
MAKE_IMMUTABLE,
- NEW_INSTANCE,
+
+ // Rely on static state
+ NEW_MUTABLE_INSTANCE,
NEW_BUILDER,
GET_DEFAULT_INSTANCE,
GET_PARSER;
@@ -188,17 +253,18 @@ public abstract class GeneratedMessageLite<
* builders in the runtime. This method bundles those operations to reduce the generated methods
* count.
* <ul>
- * <li>{@code PARSE_PARTIAL_FROM} is parameterized with an {@link CodedInputStream} and
+ * <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
+ * implementation wraps it in a RuntimeException.
+ * <li>{@code NEW_INSTANCE} returns a new instance of the protocol buffer that has not yet been
+ * made immutable. See {@code MAKE_IMMUTABLE}.
* <li>{@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to
* memoize. It returns {@code null} for false and the default instance for true. We optionally
* memoize to support the Builder case, where memoization is not desired.
* <li>{@code NEW_BUILDER} returns a {@code BuilderType} instance.
- * <li>{@code MERGE_FROM} is parameterized with a {@code MessageType} and merges the fields from
- * that instance into this 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
@@ -222,6 +288,11 @@ public abstract class GeneratedMessageLite<
return dynamicMethod(method, null, null);
}
+ void visit(Visitor visitor, MessageType other) {
+ dynamicMethod(MethodToInvoke.VISIT, visitor, other);
+ unknownFields = visitor.visitUnknownFields(unknownFields, other.unknownFields);
+ }
+
/**
* Merge some unknown fields into the {@link UnknownFieldSetLite} for this
* message.
@@ -236,7 +307,7 @@ public abstract class GeneratedMessageLite<
public abstract static class Builder<
MessageType extends GeneratedMessageLite<MessageType, BuilderType>,
BuilderType extends Builder<MessageType, BuilderType>>
- extends AbstractMessageLite.Builder<BuilderType> {
+ extends AbstractMessageLite.Builder<MessageType, BuilderType> {
private final MessageType defaultInstance;
protected MessageType instance;
@@ -244,7 +315,8 @@ public abstract class GeneratedMessageLite<
protected Builder(MessageType defaultInstance) {
this.defaultInstance = defaultInstance;
- this.instance = (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+ this.instance =
+ (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
isBuilt = false;
}
@@ -254,26 +326,27 @@ public abstract class GeneratedMessageLite<
*/
protected void copyOnWrite() {
if (isBuilt) {
- MessageType newInstance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
- newInstance.dynamicMethod(MethodToInvoke.MERGE_FROM, instance);
+ MessageType newInstance =
+ (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
+ newInstance.visit(MergeFromVisitor.INSTANCE, instance);
instance = newInstance;
isBuilt = false;
}
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final boolean isInitialized() {
return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final BuilderType clear() {
// No need to copy on write since we're dropping the instance anyways.
- instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE);
+ instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
return (BuilderType) this;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public BuilderType clone() {
BuilderType builder =
(BuilderType) getDefaultInstanceForType().newBuilderForType();
@@ -281,20 +354,19 @@ public abstract class GeneratedMessageLite<
return builder;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public MessageType buildPartial() {
if (isBuilt) {
return instance;
}
- instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
- instance.unknownFields.makeImmutable();
+ instance.makeImmutable();
isBuilt = true;
return instance;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final MessageType build() {
MessageType result = buildPartial();
if (!result.isInitialized()) {
@@ -303,32 +375,36 @@ public abstract class GeneratedMessageLite<
return result;
}
+ @Override
+ protected BuilderType internalMergeFrom(MessageType message) {
+ return mergeFrom(message);
+ }
+
/** All subclasses implement this. */
public BuilderType mergeFrom(MessageType message) {
copyOnWrite();
- instance.dynamicMethod(MethodToInvoke.MERGE_FROM, message);
+ instance.visit(MergeFromVisitor.INSTANCE, message);
return (BuilderType) this;
}
+ @Override
public MessageType getDefaultInstanceForType() {
return defaultInstance;
}
+ @Override
public BuilderType mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- MessageType parsedMessage = null;
+ throws IOException {
+ copyOnWrite();
try {
- parsedMessage = parsePartialFrom(
- (MessageType) getDefaultInstanceForType(), input, extensionRegistry);
- } catch (InvalidProtocolBufferException e) {
- parsedMessage = (MessageType) e.getUnfinishedMessage();
- throw e;
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
+ instance.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+ } catch (RuntimeException e) {
+ if (e.getCause() instanceof IOException) {
+ throw (IOException) e.getCause();
}
+ throw e;
}
return (BuilderType) this;
}
@@ -384,6 +460,12 @@ public abstract class GeneratedMessageLite<
}
extensions.mergeFrom(((ExtendableMessage) other).extensions);
}
+
+ @Override
+ final void visit(Visitor visitor, MessageType other) {
+ super.visit(visitor, other);
+ extensions = visitor.visitExtensions(extensions, other.extensions);
+ }
/**
* Parse an unknown field or an extension. For use by generated code only.
@@ -521,9 +603,8 @@ public abstract class GeneratedMessageLite<
}
/** Check if a singular extension is present. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public final <Type> boolean hasExtension(
- final ExtensionLite<MessageType, Type> extension) {
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
GeneratedExtension<MessageType, Type> extensionLite =
checkIsLite(extension);
@@ -532,7 +613,7 @@ public abstract class GeneratedMessageLite<
}
/** Get the number of elements in a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final <Type> int getExtensionCount(
final ExtensionLite<MessageType, List<Type>> extension) {
GeneratedExtension<MessageType, List<Type>> extensionLite =
@@ -543,10 +624,9 @@ public abstract class GeneratedMessageLite<
}
/** Get the value of an extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
@SuppressWarnings("unchecked")
- public final <Type> Type getExtension(
- final ExtensionLite<MessageType, Type> extension) {
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
GeneratedExtension<MessageType, Type> extensionLite =
checkIsLite(extension);
@@ -560,11 +640,10 @@ public abstract class GeneratedMessageLite<
}
/** Get one element of a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
@SuppressWarnings("unchecked")
public final <Type> Type getExtension(
- final ExtensionLite<MessageType, List<Type>> extension,
- final int index) {
+ final ExtensionLite<MessageType, List<Type>> extension, final int index) {
GeneratedExtension<MessageType, List<Type>> extensionLite =
checkIsLite(extension);
@@ -579,8 +658,8 @@ public abstract class GeneratedMessageLite<
}
@Override
- protected final void doneParsing() {
- super.doneParsing();
+ protected final void makeImmutable() {
+ super.makeImmutable();
extensions.makeImmutable();
}
@@ -669,7 +748,7 @@ public abstract class GeneratedMessageLite<
instance.extensions = extensions;
}
- // @Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
protected void copyOnWrite() {
if (!isBuilt) {
return;
@@ -679,7 +758,7 @@ public abstract class GeneratedMessageLite<
instance.extensions = instance.extensions.clone();
}
- // @Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final MessageType buildPartial() {
if (isBuilt) {
return instance;
@@ -701,33 +780,30 @@ public abstract class GeneratedMessageLite<
}
/** Check if a singular extension is present. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public final <Type> boolean hasExtension(
- final ExtensionLite<MessageType, Type> extension) {
+ @Override
+ public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extension) {
return instance.hasExtension(extension);
}
/** Get the number of elements in a repeated extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public final <Type> int getExtensionCount(
final ExtensionLite<MessageType, List<Type>> extension) {
return instance.getExtensionCount(extension);
}
/** Get the value of an extension. */
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
@SuppressWarnings("unchecked")
- public final <Type> Type getExtension(
- final ExtensionLite<MessageType, Type> extension) {
+ public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extension) {
return instance.getExtension(extension);
}
/** Get one element of a repeated extension. */
+ @Override
@SuppressWarnings("unchecked")
- //@Override (Java 1.6 override semantics, but we must support 1.5)
public final <Type> Type getExtension(
- final ExtensionLite<MessageType, List<Type>> extension,
- final int index) {
+ final ExtensionLite<MessageType, List<Type>> extension, final int index) {
return instance.getExtension(extension, index);
}
@@ -859,37 +935,44 @@ public abstract class GeneratedMessageLite<
final boolean isRepeated;
final boolean isPacked;
+ @Override
public int getNumber() {
return number;
}
+ @Override
public WireFormat.FieldType getLiteType() {
return type;
}
+ @Override
public WireFormat.JavaType getLiteJavaType() {
return type.getJavaType();
}
+ @Override
public boolean isRepeated() {
return isRepeated;
}
+ @Override
public boolean isPacked() {
return isPacked;
}
+ @Override
public Internal.EnumLiteMap<?> getEnumType() {
return enumTypeMap;
}
+ @Override
@SuppressWarnings("unchecked")
- public MessageLite.Builder internalMergeFrom(
- MessageLite.Builder to, MessageLite from) {
+ public MessageLite.Builder internalMergeFrom(MessageLite.Builder to, MessageLite from) {
return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
}
+ @Override
public int compareTo(ExtensionDescriptor other) {
return number - other.number;
}
@@ -984,6 +1067,7 @@ public abstract class GeneratedMessageLite<
}
/** Get the field number. */
+ @Override
public int getNumber() {
return descriptor.getNumber();
}
@@ -993,6 +1077,7 @@ public abstract class GeneratedMessageLite<
* If the extension is an embedded message or group, returns the default
* instance of the message.
*/
+ @Override
public MessageLite getMessageDefaultInstance() {
return messageDefaultInstance;
}
@@ -1047,14 +1132,17 @@ public abstract class GeneratedMessageLite<
}
}
+ @Override
public FieldType getLiteType() {
return descriptor.getLiteType();
}
+ @Override
public boolean isRepeated() {
return descriptor.isRepeated;
}
+ @Override
public Type getDefaultValue() {
return defaultValue;
}
@@ -1139,112 +1227,72 @@ public abstract class GeneratedMessageLite<
protected static final <T extends GeneratedMessageLite<T, ?>> boolean isInitialized(
T message, boolean shouldMemoize) {
return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null;
- }
+ }
protected static final <T extends GeneratedMessageLite<T, ?>> void makeImmutable(T message) {
message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE);
}
-
- protected static IntList newIntList() {
- return new IntArrayList();
- }
-
- protected static IntList newIntListWithCapacity(int capacity) {
- return new IntArrayList(capacity);
- }
-
- protected static IntList newIntList(List<Integer> toCopy) {
- return new IntArrayList(toCopy);
- }
-
+
protected static IntList emptyIntList() {
return IntArrayList.emptyList();
}
- protected static LongList newLongList() {
- return new LongArrayList();
+ protected static IntList mutableCopy(IntList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
}
- protected static LongList newLongListWithCapacity(int capacity) {
- return new LongArrayList(capacity);
- }
-
- protected static LongList newLongList(List<Long> toCopy) {
- return new LongArrayList(toCopy);
- }
-
protected static LongList emptyLongList() {
return LongArrayList.emptyList();
}
- protected static FloatList newFloatList() {
- return new FloatArrayList();
+ protected static LongList mutableCopy(LongList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
}
-
- protected static FloatList newFloatListWithCapacity(int capacity) {
- return new FloatArrayList(capacity);
- }
-
- protected static FloatList newFloatList(List<Float> toCopy) {
- return new FloatArrayList(toCopy);
- }
-
+
protected static FloatList emptyFloatList() {
return FloatArrayList.emptyList();
}
- protected static DoubleList newDoubleList() {
- return new DoubleArrayList();
+ protected static FloatList mutableCopy(FloatList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
}
-
- protected static DoubleList newDoubleListWithCapacity(int capacity) {
- return new DoubleArrayList(capacity);
- }
-
- protected static DoubleList newDoubleList(List<Double> toCopy) {
- return new DoubleArrayList(toCopy);
- }
-
+
protected static DoubleList emptyDoubleList() {
return DoubleArrayList.emptyList();
}
- protected static BooleanList newBooleanList() {
- return new BooleanArrayList();
- }
-
- protected static BooleanList newBooleanListWithCapacity(int capacity) {
- return new BooleanArrayList(capacity);
+ protected static DoubleList mutableCopy(DoubleList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
}
-
- protected static BooleanList newBooleanList(List<Boolean> toCopy) {
- return new BooleanArrayList(toCopy);
- }
-
+
protected static BooleanList emptyBooleanList() {
return BooleanArrayList.emptyList();
}
- protected static <E> ProtobufList<E> newProtobufList() {
- return new ProtobufArrayList<E>();
- }
-
- protected static <E> ProtobufList<E> newProtobufList(List<E> toCopy) {
- return new ProtobufArrayList<E>(toCopy);
- }
-
- protected static <E> ProtobufList<E> newProtobufListWithCapacity(int capacity) {
- return new ProtobufArrayList<E>(capacity);
+ protected static BooleanList mutableCopy(BooleanList list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
}
-
+
protected static <E> ProtobufList<E> emptyProtobufList() {
return ProtobufArrayList.emptyList();
}
-
- protected static LazyStringArrayList emptyLazyStringArrayList() {
- return LazyStringArrayList.emptyList();
- }
+ protected static <E> ProtobufList<E> mutableCopy(ProtobufList<E> list) {
+ int size = list.size();
+ return list.mutableCopyWithCapacity(
+ size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
+ }
+
/**
* A {@link Parser} implementation that delegates to the default instance.
* <p>
@@ -1274,10 +1322,11 @@ public abstract class GeneratedMessageLite<
static <T extends GeneratedMessageLite<T, ?>> T parsePartialFrom(
T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
- T result;
+ @SuppressWarnings("unchecked") // Guaranteed by protoc
+ T result = (T) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
try {
- result = (T) instance.dynamicMethod(
- MethodToInvoke.PARSE_PARTIAL_FROM, input, extensionRegistry);
+ result.dynamicMethod(MethodToInvoke.MERGE_FROM_STREAM, input, extensionRegistry);
+ result.makeImmutable();
} catch (RuntimeException e) {
if (e.getCause() instanceof InvalidProtocolBufferException) {
throw (InvalidProtocolBufferException) e.getCause();
@@ -1454,4 +1503,740 @@ public abstract class GeneratedMessageLite<
}
return message;
}
+
+ /**
+ * An abstract visitor that the generated code calls into that we use to implement various
+ * features. Fields that are not members of oneofs are always visited. Members of a oneof are only
+ * visited when they are the set oneof case value on the "other" proto. The visitOneofNotSet
+ * method is invoked if other's oneof case is not set.
+ */
+ protected interface Visitor {
+ boolean visitBoolean(boolean minePresent, boolean mine, boolean otherPresent, boolean other);
+ int visitInt(boolean minePresent, int mine, boolean otherPresent, int other);
+ double visitDouble(boolean minePresent, double mine, boolean otherPresent, double other);
+ float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other);
+ long visitLong(boolean minePresent, long mine, boolean otherPresent, long other);
+ String visitString(boolean minePresent, String mine, boolean otherPresent, String other);
+ ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other);
+
+ Object visitOneofBoolean(boolean minePresent, Object mine, Object other);
+ Object visitOneofInt(boolean minePresent, Object mine, Object other);
+ Object visitOneofDouble(boolean minePresent, Object mine, Object other);
+ Object visitOneofFloat(boolean minePresent, Object mine, Object other);
+ Object visitOneofLong(boolean minePresent, Object mine, Object other);
+ Object visitOneofString(boolean minePresent, Object mine, Object other);
+ Object visitOneofByteString(boolean minePresent, Object mine, Object other);
+ Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
+ Object visitOneofMessage(boolean minePresent, Object mine, Object other);
+ void visitOneofNotSet(boolean minePresent);
+
+ /**
+ * Message fields use null sentinals.
+ */
+ <T extends MessageLite> T visitMessage(T mine, T other);
+ LazyFieldLite visitLazyMessage(
+ boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other);
+
+ <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
+ BooleanList visitBooleanList(BooleanList mine, BooleanList other);
+ IntList visitIntList(IntList mine, IntList other);
+ DoubleList visitDoubleList(DoubleList mine, DoubleList other);
+ FloatList visitFloatList(FloatList mine, FloatList other);
+ LongList visitLongList(LongList mine, LongList other);
+ FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine, FieldSet<ExtensionDescriptor> other);
+ UnknownFieldSetLite visitUnknownFields(UnknownFieldSetLite mine, UnknownFieldSetLite other);
+ <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other);
+ }
+
+ /**
+ * Implements equals. Throws a {@link NotEqualsException} when not equal.
+ */
+ static class EqualsVisitor implements Visitor {
+
+ static final class NotEqualsException extends RuntimeException {}
+
+ static final EqualsVisitor INSTANCE = new EqualsVisitor();
+
+ static final NotEqualsException NOT_EQUALS = new NotEqualsException();
+
+ private EqualsVisitor() {}
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ if (minePresent != otherPresent || mine != other) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ if (minePresent != otherPresent || !mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ if (minePresent != otherPresent || !mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public void visitOneofNotSet(boolean minePresent) {
+ if (minePresent) {
+ throw NOT_EQUALS;
+ }
+ }
+
+ @Override
+ public <T extends MessageLite> T visitMessage(T mine, T other) {
+ if (mine == null && other == null) {
+ return null;
+ }
+
+ if (mine == null || other == null) {
+ throw NOT_EQUALS;
+ }
+
+ ((GeneratedMessageLite<?, ?>) mine).equals(this, other);
+
+ return mine;
+ }
+
+ @Override
+ public LazyFieldLite visitLazyMessage(
+ boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+ if (!minePresent && !otherPresent) {
+ return mine;
+ } else if (minePresent && otherPresent && mine.equals(other)) {
+ return mine;
+ }
+ throw NOT_EQUALS;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ if (!mine.equals(other)) {
+ throw NOT_EQUALS;
+ }
+ return mine;
+ }
+ }
+
+ /**
+ * Implements hashCode by accumulating state.
+ */
+ private static class HashCodeVisitor implements Visitor {
+
+ // The caller must ensure that the visitor is invoked parameterized with this and this such that
+ // other is this. This is required due to how oneof cases are handled. See the class comment
+ // on Visitor for more information.
+
+ private int hashCode = 0;
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ hashCode = (53 * hashCode) + Internal.hashBoolean(mine);
+ return mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ hashCode = (53 * hashCode) + mine;
+ return mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits(mine));
+ return mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ hashCode = (53 * hashCode) + Float.floatToIntBits(mine);
+ return mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(mine);
+ return mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashBoolean(((Boolean) mine));
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + (Integer) mine;
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashLong(Double.doubleToLongBits((Double) mine));
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Float.floatToIntBits((Float) mine);
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + Internal.hashLong((Long) mine);
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
+ return visitMessage((MessageLite) mine, (MessageLite) other);
+ }
+
+ @Override
+ public void visitOneofNotSet(boolean minePresent) {
+ if (minePresent) {
+ throw new IllegalStateException(); // Can't happen if other == this.
+ }
+ }
+
+ @Override
+ public <T extends MessageLite> T visitMessage(T mine, T other) {
+ final int protoHash;
+ if (mine != null) {
+ if (mine instanceof GeneratedMessageLite) {
+ protoHash = ((GeneratedMessageLite) mine).hashCode(this);
+ } else {
+ protoHash = mine.hashCode();
+ }
+ } else {
+ protoHash = 37;
+ }
+ hashCode = (53 * hashCode) + protoHash;
+ return mine;
+ }
+
+ @Override
+ public LazyFieldLite visitLazyMessage(
+ boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ hashCode = (53 * hashCode) + mine.hashCode();
+ return mine;
+ }
+ }
+
+ /**
+ * Implements field merging semantics over the visitor interface.
+ */
+ protected static class MergeFromVisitor implements Visitor {
+
+ public static final MergeFromVisitor INSTANCE = new MergeFromVisitor();
+
+ private MergeFromVisitor() {}
+
+ @Override
+ public boolean visitBoolean(
+ boolean minePresent, boolean mine, boolean otherPresent, boolean other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public int visitInt(boolean minePresent, int mine, boolean otherPresent, int other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public double visitDouble(
+ boolean minePresent, double mine, boolean otherPresent, double other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public float visitFloat(boolean minePresent, float mine, boolean otherPresent, float other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public long visitLong(boolean minePresent, long mine, boolean otherPresent, long other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public String visitString(
+ boolean minePresent, String mine, boolean otherPresent, String other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public ByteString visitByteString(
+ boolean minePresent, ByteString mine, boolean otherPresent, ByteString other) {
+ return otherPresent ? other : mine;
+ }
+
+ @Override
+ public Object visitOneofBoolean(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofInt(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofDouble(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofFloat(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofLong(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofString(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofByteString(boolean minePresent, Object mine, Object other) {
+ return other;
+ }
+
+ @Override
+ public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
+ if (minePresent) {
+ LazyFieldLite lazy = (LazyFieldLite) mine;
+ lazy.merge((LazyFieldLite) other);
+ return lazy;
+ }
+ 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 LazyFieldLite visitLazyMessage(
+ boolean minePresent, LazyFieldLite mine, boolean otherPresent, LazyFieldLite other) {
+ // LazyFieldLite's are never null so we can just copy across. Necessary to avoid leakage
+ // from builder into immutable message.
+ // TODO(dweis): Change to null sentinels?
+ mine.merge(other);
+ return mine;
+ }
+
+ @Override
+ public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public BooleanList visitBooleanList(BooleanList mine, BooleanList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public IntList visitIntList(IntList mine, IntList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public DoubleList visitDoubleList(DoubleList mine, DoubleList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public FloatList visitFloatList(FloatList mine, FloatList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public LongList visitLongList(LongList mine, LongList other) {
+ int size = mine.size();
+ int otherSize = other.size();
+ if (size > 0 && otherSize > 0) {
+ if (!mine.isModifiable()) {
+ mine = mine.mutableCopyWithCapacity(size + otherSize);
+ }
+ mine.addAll(other);
+ }
+
+ return size > 0 ? mine : other;
+ }
+
+ @Override
+ public FieldSet<ExtensionDescriptor> visitExtensions(
+ FieldSet<ExtensionDescriptor> mine,
+ FieldSet<ExtensionDescriptor> other) {
+ if (mine.isImmutable()) {
+ mine = mine.clone();
+ }
+ mine.mergeFrom(other);
+ return mine;
+ }
+
+ @Override
+ public UnknownFieldSetLite visitUnknownFields(
+ UnknownFieldSetLite mine,
+ UnknownFieldSetLite other) {
+ return other == UnknownFieldSetLite.getDefaultInstance()
+ ? mine : UnknownFieldSetLite.mutableCopyOf(mine, other);
+ }
+
+ @Override
+ public <K, V> MapFieldLite<K, V> visitMap(MapFieldLite<K, V> mine, MapFieldLite<K, V> other) {
+ mine.mergeFrom(other);
+ return mine;
+ }
+ }
}
diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
index f4e68ed8..6d6ece5a 100644
--- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.IntList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.RandomAccess;
/**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
*/
final class IntArrayList extends AbstractProtobufList<Integer> implements IntList, RandomAccess {
- private static final int DEFAULT_CAPACITY = 10;
-
private static final IntArrayList EMPTY_LIST = new IntArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class IntArrayList extends AbstractProtobufList<Integer> implements IntLis
* Constructs a new mutable {@code IntArrayList} with default capacity.
*/
IntArrayList() {
- this(DEFAULT_CAPACITY);
- }
-
- /**
- * Constructs a new mutable {@code IntArrayList} with the provided capacity.
- */
- IntArrayList(int capacity) {
- array = new int[capacity];
- size = 0;
+ this(new int[DEFAULT_CAPACITY], 0);
}
/**
* Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}.
*/
- IntArrayList(List<Integer> other) {
- if (other instanceof IntArrayList) {
- IntArrayList list = (IntArrayList) other;
- array = list.array.clone();
- size = list.size;
- } else {
- size = other.size();
- array = new int[size];
- for (int i = 0; i < size; i++) {
- array[i] = other.get(i);
+ private IntArrayList(int[] array, int size) {
+ this.array = array;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof IntArrayList)) {
+ return super.equals(o);
+ }
+ IntArrayList other = (IntArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final int[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
}
}
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + array[i];
+ }
+ return result;
+ }
+
+ @Override
+ public IntList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new IntArrayList(Arrays.copyOf(array, capacity), size);
}
@Override
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 abf7ddd6..d1de375e 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -41,6 +41,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.RandomAccess;
import java.util.Set;
/**
@@ -457,10 +458,13 @@ public final class Internal {
public static <T extends EnumLite> Converter<Integer, T> newEnumConverter(
final EnumLiteMap<T> enumMap, final T unrecognizedValue) {
return new Converter<Integer, T>() {
+ @Override
public T doForward(Integer value) {
T result = enumMap.findValueByNumber(value);
return result == null ? unrecognizedValue : result;
}
+
+ @Override
public Integer doBackward(T value) {
return value.getNumber();
}
@@ -573,8 +577,10 @@ public final class Internal {
/**
* Extends {@link List} to add the capability to make the list immutable and inspect if it is
* modifiable.
+ * <p>
+ * All implementations must support efficient random access.
*/
- public static interface ProtobufList<E> extends List<E> {
+ public static interface ProtobufList<E> extends List<E>, RandomAccess {
/**
* Makes this list immutable. All subsequent modifications will throw an
@@ -586,6 +592,11 @@ public final class Internal {
* Returns whether this list can be modified via the publicly accessible {@link List} methods.
*/
boolean isModifiable();
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ ProtobufList<E> mutableCopyWithCapacity(int capacity);
}
/**
@@ -600,14 +611,20 @@ public final class Internal {
int getInt(int index);
/**
- * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Integer)} but more efficient in that it doesn't box the element.
*/
void addInt(int element);
/**
- * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element.
*/
int setInt(int index, int element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ IntList mutableCopyWithCapacity(int capacity);
}
/**
@@ -622,14 +639,20 @@ public final class Internal {
boolean getBoolean(int index);
/**
- * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element.
*/
void addBoolean(boolean element);
/**
- * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element.
*/
boolean setBoolean(int index, boolean element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ BooleanList mutableCopyWithCapacity(int capacity);
}
/**
@@ -644,14 +667,20 @@ public final class Internal {
long getLong(int index);
/**
- * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Long)} but more efficient in that it doesn't box the element.
*/
void addLong(long element);
/**
- * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element.
*/
long setLong(int index, long element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ LongList mutableCopyWithCapacity(int capacity);
}
/**
@@ -666,14 +695,20 @@ public final class Internal {
double getDouble(int index);
/**
- * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
*/
void addDouble(double element);
/**
- * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element.
*/
double setDouble(int index, double element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ DoubleList mutableCopyWithCapacity(int capacity);
}
/**
@@ -688,13 +723,19 @@ public final class Internal {
float getFloat(int index);
/**
- * Like {@link #add(Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #add(Float)} but more efficient in that it doesn't box the element.
*/
void addFloat(float element);
/**
- * Like {@link #set(int, Object)} but more efficient in that it doesn't box the element.
+ * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element.
*/
float setFloat(int index, float element);
+
+ /**
+ * Returns a mutable clone of this list with the specified capacity.
+ */
+ @Override
+ FloatList mutableCopyWithCapacity(int capacity);
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/LazyField.java b/java/core/src/main/java/com/google/protobuf/LazyField.java
index 3da8b900..98e13ca1 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyField.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyField.java
@@ -95,12 +95,12 @@ public class LazyField extends LazyFieldLite {
this.entry = entry;
}
- // @Override
+ @Override
public K getKey() {
return entry.getKey();
}
- // @Override
+ @Override
public Object getValue() {
LazyField field = entry.getValue();
if (field == null) {
@@ -113,7 +113,7 @@ public class LazyField extends LazyFieldLite {
return entry.getValue();
}
- // @Override
+ @Override
public Object setValue(Object value) {
if (!(value instanceof MessageLite)) {
throw new IllegalArgumentException(
@@ -131,13 +131,13 @@ public class LazyField extends LazyFieldLite {
this.iterator = iterator;
}
- // @Override
+ @Override
public boolean hasNext() {
return iterator.hasNext();
}
+ @Override
@SuppressWarnings("unchecked")
- // @Override
public Entry<K, Object> next() {
Entry<K, ?> entry = iterator.next();
if (entry.getValue() instanceof LazyField) {
@@ -146,7 +146,7 @@ public class LazyField extends LazyFieldLite {
return (Entry<K, Object>) entry;
}
- // @Override
+ @Override
public void remove() {
iterator.remove();
}
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 016ec20d..2febaace 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyFieldLite.java
@@ -135,6 +135,43 @@ public class LazyFieldLite {
return lf;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof LazyFieldLite)) {
+ return false;
+ }
+
+ LazyFieldLite other = (LazyFieldLite) o;
+
+ // Lazy fields do not work well with equals... If both are delayedBytes, we do not have a
+ // mechanism to deserialize them so we rely on bytes equality. Otherwise we coerce into an
+ // actual message (if necessary) and call equals on the message itself. This implies that two
+ // messages can by unequal but then be turned equal simply be invoking a getter on a lazy field.
+ MessageLite value1 = value;
+ MessageLite value2 = other.value;
+ if (value1 == null && value2 == null) {
+ return toByteString().equals(other.toByteString());
+ } else if (value1 != null && value2 != null) {
+ return value1.equals(value2);
+ } else if (value1 != null) {
+ return value1.equals(other.getValue(value1.getDefaultInstanceForType()));
+ } else {
+ return getValue(value2.getDefaultInstanceForType()).equals(value2);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ // We can't provide a memoizable hash code for lazy fields. The byte strings may have different
+ // hash codes but evaluate to equivalent messages. And we have no facility for constructing
+ // a message here if we were not already holding a value.
+ return 1;
+ }
+
/**
* Determines whether this LazyFieldLite instance represents the default instance of this type.
*/
@@ -340,6 +377,8 @@ public class LazyFieldLite {
* parsed. Be careful when using this method.
*/
public int getSerializedSize() {
+ // We *must* return delayed bytes size if it was ever set because the dependent messages may
+ // have memoized serialized size based off of it.
if (memoizedBytes != null) {
return memoizedBytes.size();
} else if (delayedBytes != null) {
@@ -358,6 +397,8 @@ public class LazyFieldLite {
if (memoizedBytes != null) {
return memoizedBytes;
}
+ // We *must* return delayed bytes if it was set because the dependent messages may have
+ // memoized serialized size based off of it.
if (delayedBytes != null) {
return delayedBytes;
}
diff --git a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
index 68c430cf..d474c51e 100644
--- a/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java
@@ -64,7 +64,7 @@ import java.util.RandomAccess;
*/
public class LazyStringArrayList extends AbstractProtobufList<String>
implements LazyStringList, RandomAccess {
-
+
private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -80,11 +80,11 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
private final List<Object> list;
public LazyStringArrayList() {
- list = new ArrayList<Object>();
+ this(DEFAULT_CAPACITY);
}
public LazyStringArrayList(int intialCapacity) {
- list = new ArrayList<Object>(intialCapacity);
+ this(new ArrayList<Object>(intialCapacity));
}
public LazyStringArrayList(LazyStringList from) {
@@ -93,7 +93,21 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
}
public LazyStringArrayList(List<String> from) {
- list = new ArrayList<Object>(from);
+ this(new ArrayList<Object>(from));
+ }
+
+ private LazyStringArrayList(ArrayList<Object> list) {
+ this.list = list;
+ }
+
+ @Override
+ public LazyStringArrayList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size()) {
+ throw new IllegalArgumentException();
+ }
+ ArrayList<Object> newList = new ArrayList<Object>(capacity);
+ newList.addAll(list);
+ return new LazyStringArrayList(newList);
}
@Override
@@ -170,7 +184,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return ret;
}
- // @Override
+ @Override
public boolean addAllByteString(Collection<? extends ByteString> values) {
ensureIsMutable();
boolean ret = list.addAll(values);
@@ -178,7 +192,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return ret;
}
- // @Override
+ @Override
public boolean addAllByteArray(Collection<byte[]> c) {
ensureIsMutable();
boolean ret = list.addAll(c);
@@ -201,14 +215,14 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
modCount++;
}
- // @Override
+ @Override
public void add(ByteString element) {
ensureIsMutable();
list.add(element);
modCount++;
}
- // @Override
+ @Override
public void add(byte[] element) {
ensureIsMutable();
list.add(element);
@@ -220,7 +234,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return list.get(index);
}
- // @Override
+ @Override
public ByteString getByteString(int index) {
Object o = list.get(index);
ByteString b = asByteString(o);
@@ -230,7 +244,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return b;
}
- // @Override
+ @Override
public byte[] getByteArray(int index) {
Object o = list.get(index);
byte[] b = asByteArray(o);
@@ -240,7 +254,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return b;
}
- // @Override
+ @Override
public void set(int index, ByteString s) {
setAndReturn(index, s);
}
@@ -250,7 +264,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
return list.set(index, s);
}
- // @Override
+ @Override
public void set(int index, byte[] s) {
setAndReturn(index, s);
}
@@ -290,12 +304,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
}
}
- // @Override
+ @Override
public List<?> getUnderlyingElements() {
return Collections.unmodifiableList(list);
}
- // @Override
+ @Override
public void mergeFrom(LazyStringList other) {
ensureIsMutable();
for (Object o : other.getUnderlyingElements()) {
@@ -349,7 +363,7 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
}
}
- // @Override
+ @Override
public List<byte[]> asByteArrayList() {
return new ByteArrayListView(this);
}
@@ -393,12 +407,12 @@ public class LazyStringArrayList extends AbstractProtobufList<String>
}
}
- // @Override
+ @Override
public List<ByteString> asByteStringList() {
return new ByteStringListView(this);
}
- // @Override
+ @Override
public LazyStringList getUnmodifiableView() {
if (isModifiable()) {
return new UnmodifiableLazyStringList(this);
diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
index ebe62029..bc4475d1 100644
--- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -34,7 +34,6 @@ import com.google.protobuf.Internal.LongList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
import java.util.RandomAccess;
/**
@@ -44,8 +43,6 @@ import java.util.RandomAccess;
*/
final class LongArrayList extends AbstractProtobufList<Long> implements LongList, RandomAccess {
- private static final int DEFAULT_CAPACITY = 10;
-
private static final LongArrayList EMPTY_LIST = new LongArrayList();
static {
EMPTY_LIST.makeImmutable();
@@ -70,32 +67,55 @@ final class LongArrayList extends AbstractProtobufList<Long> implements LongList
* Constructs a new mutable {@code LongArrayList} with default capacity.
*/
LongArrayList() {
- this(DEFAULT_CAPACITY);
- }
-
- /**
- * Constructs a new mutable {@code LongArrayList} with the provided capacity.
- */
- LongArrayList(int capacity) {
- array = new long[capacity];
- size = 0;
+ this(new long[DEFAULT_CAPACITY], 0);
}
/**
* Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}.
*/
- LongArrayList(List<Long> other) {
- if (other instanceof LongArrayList) {
- LongArrayList list = (LongArrayList) other;
- array = list.array.clone();
- size = list.size;
- } else {
- size = other.size();
- array = new long[size];
- for (int i = 0; i < size; i++) {
- array[i] = other.get(i);
+ private LongArrayList(long[] array, int size) {
+ this.array = array;
+ this.size = size;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof IntArrayList)) {
+ return super.equals(o);
+ }
+ LongArrayList other = (LongArrayList) o;
+ if (size != other.size) {
+ return false;
+ }
+
+ final long[] arr = other.array;
+ for (int i = 0; i < size; i++) {
+ if (array[i] != arr[i]) {
+ return false;
}
}
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ for (int i = 0; i < size; i++) {
+ result = (31 * result) + Internal.hashLong(array[i]);
+ }
+ return result;
+ }
+
+ @Override
+ public LongList mutableCopyWithCapacity(int capacity) {
+ if (capacity < size) {
+ throw new IllegalArgumentException();
+ }
+ return new LongArrayList(Arrays.copyOf(array, capacity), size);
}
@Override
diff --git a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
index bcffa946..12c64abb 100644
--- a/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MapEntryLite.java
@@ -41,7 +41,8 @@ import java.io.IOException;
*
* Protobuf internal. Users shouldn't use.
*/
-public class MapEntryLite<K, V> extends AbstractMessageLite {
+public class MapEntryLite<K, V>
+ extends AbstractMessageLite<MapEntryLite<K, V>, MapEntryLite.Builder<K, V>> {
private static class Metadata<K, V> {
public final MapEntryLite<K, V> defaultInstance;
public final WireFormat.FieldType keyType;
@@ -233,7 +234,7 @@ public class MapEntryLite<K, V> extends AbstractMessageLite {
* Builder used to create {@link MapEntryLite} messages.
*/
public static class Builder<K, V>
- extends AbstractMessageLite.Builder<Builder<K, V>> {
+ extends AbstractMessageLite.Builder<MapEntryLite<K, V>, Builder<K, V>> {
private final Metadata<K, V> metadata;
private K key;
private V value;
@@ -327,5 +328,10 @@ public class MapEntryLite<K, V> extends AbstractMessageLite {
this.value = entry.value;
return this;
}
+
+ @Override
+ protected Builder<K, V> internalMergeFrom(MapEntryLite<K, V> message) {
+ throw new UnsupportedOperationException();
+ }
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/MapField.java b/java/core/src/main/java/com/google/protobuf/MapField.java
index b290993c..907f0f71 100644
--- a/java/core/src/main/java/com/google/protobuf/MapField.java
+++ b/java/core/src/main/java/com/google/protobuf/MapField.java
@@ -93,15 +93,18 @@ public class MapField<K, V> implements MutabilityOracle {
this.defaultEntry = defaultEntry;
}
+ @Override
public Message convertKeyAndValueToMessage(K key, V value) {
return defaultEntry.newBuilderForType().setKey(key).setValue(value).buildPartial();
}
+ @Override
public void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
MapEntry<K, V> entry = (MapEntry<K, V>) message;
map.put(entry.getKey(), entry.getValue());
}
+ @Override
public Message getMessageDefaultInstance() {
return defaultEntry;
}
diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java
index 9516d71f..94590fb9 100644
--- a/java/core/src/main/java/com/google/protobuf/Message.java
+++ b/java/core/src/main/java/com/google/protobuf/Message.java
@@ -51,6 +51,7 @@ import java.util.Map;
public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
+ @Override
Parser<? extends Message> getParserForType();
@@ -97,7 +98,10 @@ public interface Message extends MessageLite, MessageOrBuilder {
// Builders
// (From MessageLite, re-declared here only for return type covariance.)
+ @Override
Builder newBuilderForType();
+
+ @Override
Builder toBuilder();
/**
@@ -106,6 +110,7 @@ public interface Message extends MessageLite, MessageOrBuilder {
interface Builder extends MessageLite.Builder, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
+ @Override
Builder clear();
/**
@@ -131,18 +136,27 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
+ @Override
Message build();
+
+ @Override
Message buildPartial();
+
+ @Override
Builder clone();
+
+ @Override
Builder mergeFrom(CodedInputStream input) throws IOException;
- Builder mergeFrom(CodedInputStream input,
- ExtensionRegistryLite extensionRegistry)
- throws IOException;
+
+ @Override
+ Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
/**
* Get the message's type's descriptor.
* See {@link Message#getDescriptorForType()}.
*/
+ @Override
Descriptors.Descriptor getDescriptorForType();
/**
@@ -240,27 +254,39 @@ public interface Message extends MessageLite, MessageOrBuilder {
// (From MessageLite.Builder, re-declared here only for return type
// covariance.)
+ @Override
Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
- Builder mergeFrom(ByteString data,
- ExtensionRegistryLite extensionRegistry)
- throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
- Builder mergeFrom(byte[] data, int off, int len)
- throws InvalidProtocolBufferException;
- Builder mergeFrom(byte[] data,
- ExtensionRegistryLite extensionRegistry)
- throws InvalidProtocolBufferException;
- Builder mergeFrom(byte[] data, int off, int len,
- ExtensionRegistryLite extensionRegistry)
- throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
+ Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
+ throws InvalidProtocolBufferException;
+
+ @Override
Builder mergeFrom(InputStream input) throws IOException;
- Builder mergeFrom(InputStream input,
- ExtensionRegistryLite extensionRegistry)
- throws IOException;
- boolean mergeDelimitedFrom(InputStream input)
- throws IOException;
- boolean mergeDelimitedFrom(InputStream input,
- ExtensionRegistryLite extensionRegistry)
- throws IOException;
+
+ @Override
+ Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
+
+ @Override
+ boolean mergeDelimitedFrom(InputStream input) throws IOException;
+
+ @Override
+ boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException;
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageLite.java b/java/core/src/main/java/com/google/protobuf/MessageLite.java
index 798b7943..88f531df 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageLite.java
@@ -295,6 +295,27 @@ public interface MessageLite extends MessageLiteOrBuilder {
Builder mergeFrom(InputStream input,
ExtensionRegistryLite extensionRegistry)
throws IOException;
+
+ /**
+ * Merge {@code other} into the message being built. {@code other} must
+ * have the exact same type as {@code this} (i.e.
+ * {@code getClass().equals(getDefaultInstanceForType().getClass())}).
+ *
+ * Merging occurs as follows. For each field:<br>
+ * * For singular primitive fields, if the field is set in {@code other},
+ * then {@code other}'s value overwrites the value in this message.<br>
+ * * For singular message fields, if the field is set in {@code other},
+ * it is merged into the corresponding sub-message of this message
+ * using the same merging rules.<br>
+ * * For repeated fields, the elements in {@code other} are concatenated
+ * with the elements in this message.
+ * * For oneof groups, if the other message has one of the fields set,
+ * the group of this message is cleared and replaced by the field
+ * of the other message, so that the oneof constraint is preserved.
+ *
+ * This is equivalent to the {@code Message::MergeFrom} method in C++.
+ */
+ Builder mergeFrom(MessageLite other);
/**
* Like {@link #mergeFrom(InputStream)}, but does not read until EOF.
diff --git a/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java b/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
index 2a6e0e30..43847651 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageLiteToString.java
@@ -30,23 +30,24 @@
package com.google.protobuf;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
/**
* Helps generate {@link String} representations of {@link MessageLite} protos.
*/
+// TODO(dweis): Fix map fields.
final class MessageLiteToString {
- /**
- * Suffix for *_FIELD_NUMBER fields. This is used to reflectively detect proto fields that should
- * be toString()ed.
- */
- private static final String FIELD_NUMBER_NAME_SUFFIX = "_FIELD_NUMBER";
+ private static final String LIST_SUFFIX = "List";
+ private static final String BUILDER_LIST_SUFFIX = "OrBuilderList";
+ private static final String BYTES_SUFFIX = "Bytes";
+
/**
* Returns a {@link String} representation of the {@link MessageLite} object. The first line of
* the {@code String} representation representation includes a comment string to uniquely identify
@@ -73,52 +74,70 @@ final class MessageLiteToString {
// Build a map of method name to method. We're looking for methods like getFoo(), hasFoo(), and
// getFooList() which might be useful for building an object's string representation.
Map<String, Method> nameToNoArgMethod = new HashMap<String, Method>();
+ Map<String, Method> nameToMethod = new HashMap<String, Method>();
+ Set<String> getters = new TreeSet<String>();
for (Method method : messageLite.getClass().getDeclaredMethods()) {
+ nameToMethod.put(method.getName(), method);
if (method.getParameterTypes().length == 0) {
nameToNoArgMethod.put(method.getName(), method);
+
+ if (method.getName().startsWith("get")) {
+ getters.add(method.getName());
+ }
}
}
- for (Field field : messageLite.getClass().getDeclaredFields()) {
- String fieldName = field.getName();
- // Skip all fields that aren't in a format like "FOO_BAR_FIELD_NUMBER"
- if (!fieldName.endsWith(FIELD_NUMBER_NAME_SUFFIX)) {
- continue;
+ for (String getter : getters) {
+ String suffix = getter.replaceFirst("get", "");
+ if (suffix.endsWith(LIST_SUFFIX) && !suffix.endsWith(BUILDER_LIST_SUFFIX)) {
+ String camelCase = suffix.substring(0, 1).toLowerCase()
+ + suffix.substring(1, suffix.length() - LIST_SUFFIX.length());
+ // Try to reflectively get the value and toString() the field as if it were repeated. This
+ // only works if the method names have not be proguarded out or renamed.
+ Method listMethod = nameToNoArgMethod.get("get" + suffix);
+ if (listMethod != null) {
+ printField(
+ buffer,
+ indent,
+ camelCaseToSnakeCase(camelCase),
+ GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
+ continue;
+ }
}
- // For "FOO_BAR_FIELD_NUMBER" his would be "FOO_BAR"
- String upperUnderscore =
- fieldName.substring(0, fieldName.length() - FIELD_NUMBER_NAME_SUFFIX.length());
-
- // For "FOO_BAR_FIELD_NUMBER" his would be "FooBar"
- String upperCamelCaseName = upperUnderscoreToUpperCamel(upperUnderscore);
+ Method setter = nameToMethod.get("set" + suffix);
+ if (setter == null) {
+ continue;
+ }
+ if (suffix.endsWith(BYTES_SUFFIX)
+ && nameToNoArgMethod.containsKey(
+ "get" + suffix.substring(0, suffix.length() - "Bytes".length()))) {
+ // Heuristic to skip bytes based accessors for string fields.
+ continue;
+ }
+
+ String camelCase = suffix.substring(0, 1).toLowerCase() + suffix.substring(1);
// Try to reflectively get the value and toString() the field as if it were optional. This
// only works if the method names have not be proguarded out or renamed.
- Method getMethod = nameToNoArgMethod.get("get" + upperCamelCaseName);
- Method hasMethod = nameToNoArgMethod.get("has" + upperCamelCaseName);
- if (getMethod != null && hasMethod != null) {
- if ((Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite)) {
+ Method getMethod = nameToNoArgMethod.get("get" + suffix);
+ Method hasMethod = nameToNoArgMethod.get("has" + suffix);
+ // TODO(dweis): Fix proto3 semantics.
+ if (getMethod != null) {
+ Object value = GeneratedMessageLite.invokeOrDie(getMethod, messageLite);
+ final boolean hasValue = hasMethod == null
+ ? !isDefaultValue(value)
+ : (Boolean) GeneratedMessageLite.invokeOrDie(hasMethod, messageLite);
+ // TODO(dweis): This doesn't stop printing oneof case twice: value and enum style.
+ if (hasValue) {
printField(
buffer,
indent,
- upperUnderscore.toLowerCase(),
- GeneratedMessageLite.invokeOrDie(getMethod, messageLite));
+ camelCaseToSnakeCase(camelCase),
+ value);
}
continue;
}
-
- // Try to reflectively get the value and toString() the field as if it were repeated. This
- // only works if the method names have not be proguarded out or renamed.
- Method listMethod = nameToNoArgMethod.get("get" + upperCamelCaseName + "List");
- if (listMethod != null) {
- printField(
- buffer,
- indent,
- upperUnderscore.toLowerCase(),
- GeneratedMessageLite.invokeOrDie(listMethod, messageLite));
- continue;
- }
}
if (messageLite instanceof GeneratedMessageLite.ExtendableMessage) {
@@ -130,10 +149,39 @@ final class MessageLiteToString {
}
}
- if (((GeneratedMessageLite) messageLite).unknownFields != null) {
- ((GeneratedMessageLite) messageLite).unknownFields.printWithIndent(buffer, indent);
+ if (((GeneratedMessageLite<?, ?>) messageLite).unknownFields != null) {
+ ((GeneratedMessageLite<?, ?>) messageLite).unknownFields.printWithIndent(buffer, indent);
}
}
+
+ private static boolean isDefaultValue(Object o) {
+ if (o instanceof Boolean) {
+ return !((Boolean) o);
+ }
+ if (o instanceof Integer) {
+ return ((Integer) o) == 0;
+ }
+ if (o instanceof Float) {
+ return ((Float) o) == 0f;
+ }
+ if (o instanceof Double) {
+ return ((Double) o) == 0d;
+ }
+ if (o instanceof String) {
+ return o.equals("");
+ }
+ if (o instanceof ByteString) {
+ return o.equals(ByteString.EMPTY);
+ }
+ if (o instanceof MessageLite) { // Can happen in oneofs.
+ return o == ((MessageLite) o).getDefaultInstanceForType();
+ }
+ if (o instanceof java.lang.Enum<?>) { // Catches oneof enums.
+ return ((java.lang.Enum<?>) o).ordinal() == 0;
+ }
+
+ return false;
+ }
/**
* Formats a text proto field.
@@ -166,7 +214,7 @@ final class MessageLiteToString {
buffer.append(": \"").append(TextFormatEscaper.escapeBytes((ByteString) object)).append('"');
} else if (object instanceof GeneratedMessageLite) {
buffer.append(" {");
- reflectivePrintWithIndent((GeneratedMessageLite) object, buffer, indent + 2);
+ reflectivePrintWithIndent((GeneratedMessageLite<?, ?>) object, buffer, indent + 2);
buffer.append("\n");
for (int i = 0; i < indent; i++) {
buffer.append(' ');
@@ -176,25 +224,16 @@ final class MessageLiteToString {
buffer.append(": ").append(object.toString());
}
}
-
- /**
- * A Guava-less implementation of:
- * {@code CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, upperUnderscore)}
- */
- private static String upperUnderscoreToUpperCamel(String upperUnderscore) {
- String upperCamelCaseName = "";
- boolean nextCharacterShouldBeUpper = true;
- for (int i = 0; i < upperUnderscore.length(); i++) {
- char ch = upperUnderscore.charAt(i);
- if (ch == '_') {
- nextCharacterShouldBeUpper = true;
- } else if (nextCharacterShouldBeUpper){
- upperCamelCaseName += Character.toUpperCase(ch);
- nextCharacterShouldBeUpper = false;
- } else {
- upperCamelCaseName += Character.toLowerCase(ch);
+
+ private static final String camelCaseToSnakeCase(String camelCase) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < camelCase.length(); i++) {
+ char ch = camelCase.charAt(i);
+ if (Character.isUpperCase(ch)) {
+ builder.append("_");
}
+ builder.append(Character.toLowerCase(ch));
}
- return upperCamelCaseName;
+ return builder.toString();
}
}
diff --git a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
index f0fc4859..5e7d7821 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -42,7 +42,7 @@ import java.util.Map;
public interface MessageOrBuilder extends MessageLiteOrBuilder {
// (From MessageLite, re-declared here only for return type covariance.)
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
Message getDefaultInstanceForType();
/**
diff --git a/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
index de4bfd3e..7b791d9e 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
@@ -364,12 +364,14 @@ class MessageReflection {
* Finishes the merge and returns the underlying object.
*/
Object finish();
+
}
static class BuilderAdapter implements MergeTarget {
private final Message.Builder builder;
+ @Override
public Descriptors.Descriptor getDescriptorForType() {
return builder.getDescriptorForType();
}
@@ -378,6 +380,7 @@ class MessageReflection {
this.builder = builder;
}
+ @Override
public Object getField(Descriptors.FieldDescriptor field) {
return builder.getField(field);
}
@@ -387,25 +390,27 @@ class MessageReflection {
return builder.hasField(field);
}
- public MergeTarget setField(Descriptors.FieldDescriptor field,
- Object value) {
+ @Override
+ public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
builder.setField(field, value);
return this;
}
+ @Override
public MergeTarget clearField(Descriptors.FieldDescriptor field) {
builder.clearField(field);
return this;
}
+ @Override
public MergeTarget setRepeatedField(
Descriptors.FieldDescriptor field, int index, Object value) {
builder.setRepeatedField(field, index, value);
return this;
}
- public MergeTarget addRepeatedField(
- Descriptors.FieldDescriptor field, Object value) {
+ @Override
+ public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
builder.addRepeatedField(field, value);
return this;
}
@@ -426,25 +431,30 @@ class MessageReflection {
return builder.getOneofFieldDescriptor(oneof);
}
+ @Override
public ContainerType getContainerType() {
return ContainerType.MESSAGE;
}
+ @Override
public ExtensionRegistry.ExtensionInfo findExtensionByName(
ExtensionRegistry registry, String name) {
return registry.findImmutableExtensionByName(name);
}
+ @Override
public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
- ExtensionRegistry registry, Descriptors.Descriptor containingType,
- int fieldNumber) {
+ ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
return registry.findImmutableExtensionByNumber(containingType,
fieldNumber);
}
- public Object parseGroup(CodedInputStream input,
+ @Override
+ public Object parseGroup(
+ CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
- Descriptors.FieldDescriptor field, Message defaultInstance)
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
throws IOException {
Message.Builder subBuilder;
// When default instance is not null. The field is an extension field.
@@ -463,9 +473,12 @@ class MessageReflection {
return subBuilder.buildPartial();
}
- public Object parseMessage(CodedInputStream input,
+ @Override
+ public Object parseMessage(
+ CodedInputStream input,
ExtensionRegistryLite extensionRegistry,
- Descriptors.FieldDescriptor field, Message defaultInstance)
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
throws IOException {
Message.Builder subBuilder;
// When default instance is not null. The field is an extension field.
@@ -484,9 +497,12 @@ class MessageReflection {
return subBuilder.buildPartial();
}
- public Object parseMessageFromBytes(ByteString bytes,
+ @Override
+ public Object parseMessageFromBytes(
+ ByteString bytes,
ExtensionRegistryLite extensionRegistry,
- Descriptors.FieldDescriptor field, Message defaultInstance)
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
throws IOException {
Message.Builder subBuilder;
// When default instance is not null. The field is an extension field.
@@ -505,8 +521,9 @@ class MessageReflection {
return subBuilder.buildPartial();
}
- public MergeTarget newMergeTargetForField(Descriptors.FieldDescriptor field,
- Message defaultInstance) {
+ @Override
+ public MergeTarget newMergeTargetForField(
+ Descriptors.FieldDescriptor field, Message defaultInstance) {
if (defaultInstance != null) {
return new BuilderAdapter(
defaultInstance.newBuilderForType());
@@ -515,8 +532,8 @@ class MessageReflection {
}
}
- public WireFormat.Utf8Validation
- getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ @Override
+ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
if (descriptor.needsUtf8Check()) {
return WireFormat.Utf8Validation.STRICT;
}
@@ -528,9 +545,11 @@ class MessageReflection {
return WireFormat.Utf8Validation.LOOSE;
}
+ @Override
public Object finish() {
return builder.buildPartial();
}
+
}
@@ -542,38 +561,43 @@ class MessageReflection {
this.extensions = extensions;
}
+ @Override
public Descriptors.Descriptor getDescriptorForType() {
throw new UnsupportedOperationException(
"getDescriptorForType() called on FieldSet object");
}
+ @Override
public Object getField(Descriptors.FieldDescriptor field) {
return extensions.getField(field);
}
+ @Override
public boolean hasField(Descriptors.FieldDescriptor field) {
return extensions.hasField(field);
}
- public MergeTarget setField(Descriptors.FieldDescriptor field,
- Object value) {
+ @Override
+ public MergeTarget setField(Descriptors.FieldDescriptor field, Object value) {
extensions.setField(field, value);
return this;
}
+ @Override
public MergeTarget clearField(Descriptors.FieldDescriptor field) {
extensions.clearField(field);
return this;
}
+ @Override
public MergeTarget setRepeatedField(
Descriptors.FieldDescriptor field, int index, Object value) {
extensions.setRepeatedField(field, index, value);
return this;
}
- public MergeTarget addRepeatedField(
- Descriptors.FieldDescriptor field, Object value) {
+ @Override
+ public MergeTarget addRepeatedField(Descriptors.FieldDescriptor field, Object value) {
extensions.addRepeatedField(field, value);
return this;
}
@@ -594,25 +618,31 @@ class MessageReflection {
return null;
}
+ @Override
public ContainerType getContainerType() {
return ContainerType.EXTENSION_SET;
}
+ @Override
public ExtensionRegistry.ExtensionInfo findExtensionByName(
ExtensionRegistry registry, String name) {
return registry.findImmutableExtensionByName(name);
}
+ @Override
public ExtensionRegistry.ExtensionInfo findExtensionByNumber(
- ExtensionRegistry registry, Descriptors.Descriptor containingType,
- int fieldNumber) {
+ ExtensionRegistry registry, Descriptors.Descriptor containingType, int fieldNumber) {
return registry.findImmutableExtensionByNumber(containingType,
fieldNumber);
}
- public Object parseGroup(CodedInputStream input,
- ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
- Message defaultInstance) throws IOException {
+ @Override
+ public Object parseGroup(
+ CodedInputStream input,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
Message.Builder subBuilder =
defaultInstance.newBuilderForType();
if (!field.isRepeated()) {
@@ -625,9 +655,13 @@ class MessageReflection {
return subBuilder.buildPartial();
}
- public Object parseMessage(CodedInputStream input,
- ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
- Message defaultInstance) throws IOException {
+ @Override
+ public Object parseMessage(
+ CodedInputStream input,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
Message.Builder subBuilder =
defaultInstance.newBuilderForType();
if (!field.isRepeated()) {
@@ -640,9 +674,13 @@ class MessageReflection {
return subBuilder.buildPartial();
}
- public Object parseMessageFromBytes(ByteString bytes,
- ExtensionRegistryLite registry, Descriptors.FieldDescriptor field,
- Message defaultInstance) throws IOException {
+ @Override
+ public Object parseMessageFromBytes(
+ ByteString bytes,
+ ExtensionRegistryLite registry,
+ Descriptors.FieldDescriptor field,
+ Message defaultInstance)
+ throws IOException {
Message.Builder subBuilder = defaultInstance.newBuilderForType();
if (!field.isRepeated()) {
Message originalMessage = (Message) getField(field);
@@ -654,14 +692,15 @@ class MessageReflection {
return subBuilder.buildPartial();
}
+ @Override
public MergeTarget newMergeTargetForField(
Descriptors.FieldDescriptor descriptor, Message defaultInstance) {
throw new UnsupportedOperationException(
"newMergeTargetForField() called on FieldSet object");
}
- public WireFormat.Utf8Validation
- getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
+ @Override
+ public WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor descriptor) {
if (descriptor.needsUtf8Check()) {
return WireFormat.Utf8Validation.STRICT;
}
@@ -669,10 +708,12 @@ class MessageReflection {
return WireFormat.Utf8Validation.LOOSE;
}
+ @Override
public Object finish() {
throw new UnsupportedOperationException(
"finish() called on FieldSet object");
}
+
}
/**
diff --git a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
index d2f82ac5..81255ec2 100644
--- a/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java
@@ -38,7 +38,7 @@ import java.util.List;
/**
* Implements {@link ProtobufList} for non-primitive and {@link String} types.
*/
-class ProtobufArrayList<E> extends AbstractProtobufList<E> {
+final class ProtobufArrayList<E> extends AbstractProtobufList<E> {
private static final ProtobufArrayList<Object> EMPTY_LIST = new ProtobufArrayList<Object>();
static {
@@ -51,17 +51,23 @@ class ProtobufArrayList<E> extends AbstractProtobufList<E> {
}
private final List<E> list;
-
+
ProtobufArrayList() {
- list = new ArrayList<E>();
+ this(new ArrayList<E>(DEFAULT_CAPACITY));
}
- ProtobufArrayList(List<E> toCopy) {
- list = new ArrayList<E>(toCopy);
+ private ProtobufArrayList(List<E> list) {
+ this.list = list;
}
-
- ProtobufArrayList(int capacity) {
- list = new ArrayList<E>(capacity);
+
+ @Override
+ public ProtobufArrayList<E> mutableCopyWithCapacity(int capacity) {
+ if (capacity < size()) {
+ throw new IllegalArgumentException();
+ }
+ List<E> newList = new ArrayList<E>(capacity);
+ newList.addAll(list);
+ return new ProtobufArrayList<E>(newList);
}
@Override
diff --git a/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java b/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
index 0c8df989..a596d301 100644
--- a/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
+++ b/java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java
@@ -42,6 +42,7 @@ public interface ProtocolMessageEnum extends Internal.EnumLite {
/**
* Return the value's numeric value as defined in the .proto file.
*/
+ @Override
int getNumber();
/**
diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index f91cdbce..29f567dc 100644
--- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -579,7 +579,7 @@ public class RepeatedFieldBuilder
}
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void markDirty() {
onChanged();
}
@@ -621,10 +621,12 @@ public class RepeatedFieldBuilder
this.builder = builder;
}
+ @Override
public int size() {
return this.builder.getCount();
}
+ @Override
public MType get(int index) {
return builder.getMessage(index);
}
@@ -654,10 +656,12 @@ public class RepeatedFieldBuilder
this.builder = builder;
}
+ @Override
public int size() {
return this.builder.getCount();
}
+ @Override
public BType get(int index) {
return builder.getBuilder(index);
}
@@ -687,10 +691,12 @@ public class RepeatedFieldBuilder
this.builder = builder;
}
+ @Override
public int size() {
return this.builder.getCount();
}
+ @Override
public IType get(int index) {
return builder.getMessageOrBuilder(index);
}
diff --git a/java/core/src/main/java/com/google/protobuf/RpcUtil.java b/java/core/src/main/java/com/google/protobuf/RpcUtil.java
index 694b8d13..f7d555ae 100644
--- a/java/core/src/main/java/com/google/protobuf/RpcUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/RpcUtil.java
@@ -71,6 +71,7 @@ public final class RpcUtil {
final Class<Type> originalClass,
final Type defaultInstance) {
return new RpcCallback<Message>() {
+ @Override
public void run(final Message parameter) {
Type typedParameter;
try {
@@ -107,8 +108,9 @@ public final class RpcUtil {
return new RpcCallback<ParameterType>() {
private boolean alreadyCalled = false;
+ @Override
public void run(final ParameterType parameter) {
- synchronized(this) {
+ synchronized (this) {
if (alreadyCalled) {
throw new AlreadyCalledException();
}
diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index aba65e32..941b5def 100644
--- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -234,7 +234,7 @@ public class SingleFieldBuilder
}
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void markDirty() {
onChanged();
}
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 dff19328..409fec10 100644
--- a/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
+++ b/java/core/src/main/java/com/google/protobuf/SmallSortedMap.java
@@ -411,22 +411,22 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
this.value = value;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public K getKey() {
return key;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public V getValue() {
return value;
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public int compareTo(Entry other) {
return getKey().compareTo(other.getKey());
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public V setValue(V newValue) {
checkMutable();
final V oldValue = this.value;
@@ -535,13 +535,13 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
private boolean nextCalledBeforeRemove;
private Iterator<Map.Entry<K, V>> lazyOverflowIterator;
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasNext() {
return (pos + 1) < entryList.size() ||
getOverflowIterator().hasNext();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public Map.Entry<K, V> next() {
nextCalledBeforeRemove = true;
// Always increment pos so that we know whether the last returned value
@@ -552,7 +552,7 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
return getOverflowIterator().next();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void remove() {
if (!nextCalledBeforeRemove) {
throw new IllegalStateException("remove() was called before next()");
@@ -588,31 +588,83 @@ class SmallSortedMap<K extends Comparable<K>, V> extends AbstractMap<K, V> {
*/
private static class EmptySet {
- private static final Iterator<Object> ITERATOR = new Iterator<Object>() {
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public boolean hasNext() {
- return false;
- }
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public Object next() {
- throw new NoSuchElementException();
- }
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
+ private static final Iterator<Object> ITERATOR =
+ new Iterator<Object>() {
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+ @Override
+ public Object next() {
+ throw new NoSuchElementException();
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
- private static final Iterable<Object> ITERABLE = new Iterable<Object>() {
- //@Override (Java 1.6 override semantics, but we must support 1.5)
- public Iterator<Object> iterator() {
- return ITERATOR;
- }
- };
+ private static final Iterable<Object> ITERABLE =
+ new Iterable<Object>() {
+ @Override
+ public Iterator<Object> iterator() {
+ return ITERATOR;
+ }
+ };
@SuppressWarnings("unchecked")
static <T> Iterable<T> iterable() {
return (Iterable<T>) ITERABLE;
}
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (!(o instanceof SmallSortedMap)) {
+ return super.equals(o);
+ }
+
+ SmallSortedMap<?, ?> other = (SmallSortedMap<?, ?>) o;
+ final int size = size();
+ if (size != other.size()) {
+ return false;
+ }
+
+ // Best effort try to avoid allocating an entry set.
+ final int numArrayEntries = getNumArrayEntries();
+ if (numArrayEntries != other.getNumArrayEntries()) {
+ return entrySet().equals(other.entrySet());
+ }
+
+ for (int i = 0; i < numArrayEntries; i++) {
+ if (!getArrayEntryAt(i).equals(other.getArrayEntryAt(i))) {
+ return false;
+ }
+ }
+
+ if (numArrayEntries != size) {
+ return overflowEntries.equals(other.overflowEntries);
+ }
+
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = 0;
+ final int listSize = getNumArrayEntries();
+ for (int i = 0; i < listSize; i++) {
+ h += entryList.get(i).hashCode();
+ }
+ // Avoid the iterator allocation if possible.
+ if (getNumOverflowEntries() > 0) {
+ h += overflowEntries.hashCode();
+ }
+ return h;
+ }
}
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index edf114fa..c1c328fc 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -965,11 +965,13 @@ public final class TextFormat {
*/
public boolean consumeBoolean() throws ParseException {
if (currentToken.equals("true")
+ || currentToken.equals("True")
|| currentToken.equals("t")
|| currentToken.equals("1")) {
nextToken();
return true;
} else if (currentToken.equals("false")
+ || currentToken.equals("False")
|| currentToken.equals("f")
|| currentToken.equals("0")) {
nextToken();
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 7cd2250e..c906420d 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -76,6 +76,7 @@ public final class UnknownFieldSet implements MessageLite {
public static UnknownFieldSet getDefaultInstance() {
return defaultInstance;
}
+ @Override
public UnknownFieldSet getDefaultInstanceForType() {
return defaultInstance;
}
@@ -126,6 +127,7 @@ public final class UnknownFieldSet implements MessageLite {
}
/** Serializes the set and writes it to {@code output}. */
+ @Override
public void writeTo(final CodedOutputStream output) throws IOException {
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
entry.getValue().writeTo(entry.getKey(), output);
@@ -146,6 +148,7 @@ public final class UnknownFieldSet implements MessageLite {
* Serializes the message to a {@code ByteString} and returns it. This is
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
+ @Override
public ByteString toByteString() {
try {
final ByteString.CodedBuilder out =
@@ -163,6 +166,7 @@ public final class UnknownFieldSet implements MessageLite {
* Serializes the message to a {@code byte} array and returns it. This is
* just a trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
+ @Override
public byte[] toByteArray() {
try {
final byte[] result = new byte[getSerializedSize()];
@@ -181,12 +185,14 @@ public final class UnknownFieldSet implements MessageLite {
* Serializes the message and writes it to {@code output}. This is just a
* trivial wrapper around {@link #writeTo(CodedOutputStream)}.
*/
+ @Override
public void writeTo(final OutputStream output) throws IOException {
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
writeTo(codedOutput);
codedOutput.flush();
}
+ @Override
public void writeDelimitedTo(OutputStream output) throws IOException {
final CodedOutputStream codedOutput = CodedOutputStream.newInstance(output);
codedOutput.writeRawVarint32(getSerializedSize());
@@ -195,6 +201,7 @@ public final class UnknownFieldSet implements MessageLite {
}
/** Get the number of bytes required to encode this set. */
+ @Override
public int getSerializedSize() {
int result = 0;
for (final Map.Entry<Integer, Field> entry : fields.entrySet()) {
@@ -228,6 +235,7 @@ public final class UnknownFieldSet implements MessageLite {
return result;
}
+ @Override
public boolean isInitialized() {
// UnknownFieldSets do not have required fields, so they are always
// initialized.
@@ -258,10 +266,12 @@ public final class UnknownFieldSet implements MessageLite {
return newBuilder().mergeFrom(input).build();
}
+ @Override
public Builder newBuilderForType() {
return newBuilder();
}
+ @Override
public Builder toBuilder() {
return newBuilder().mergeFrom(this);
}
@@ -329,6 +339,7 @@ public final class UnknownFieldSet implements MessageLite {
* in undefined behavior and can cause a {@code NullPointerException} to be
* thrown.
*/
+ @Override
public UnknownFieldSet build() {
getFieldBuilder(0); // Force lastField to be built.
final UnknownFieldSet result;
@@ -341,6 +352,7 @@ public final class UnknownFieldSet implements MessageLite {
return result;
}
+ @Override
public UnknownFieldSet buildPartial() {
// No required fields, so this is the same as build().
return build();
@@ -353,6 +365,7 @@ public final class UnknownFieldSet implements MessageLite {
new UnknownFieldSet(fields));
}
+ @Override
public UnknownFieldSet getDefaultInstanceForType() {
return UnknownFieldSet.getDefaultInstance();
}
@@ -364,6 +377,7 @@ public final class UnknownFieldSet implements MessageLite {
}
/** Reset the builder to an empty set. */
+ @Override
public Builder clear() {
reinitialize();
return this;
@@ -487,6 +501,7 @@ public final class UnknownFieldSet implements MessageLite {
* Parse an entire message from {@code input} and merge its fields into
* this set.
*/
+ @Override
public Builder mergeFrom(final CodedInputStream input) throws IOException {
while (true) {
final int tag = input.readTag();
@@ -536,8 +551,8 @@ public final class UnknownFieldSet implements MessageLite {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
- public Builder mergeFrom(final ByteString data)
- throws InvalidProtocolBufferException {
+ @Override
+ public Builder mergeFrom(final ByteString data) throws InvalidProtocolBufferException {
try {
final CodedInputStream input = data.newCodedInput();
mergeFrom(input);
@@ -557,8 +572,8 @@ public final class UnknownFieldSet implements MessageLite {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
- public Builder mergeFrom(final byte[] data)
- throws InvalidProtocolBufferException {
+ @Override
+ public Builder mergeFrom(final byte[] data) throws InvalidProtocolBufferException {
try {
final CodedInputStream input = CodedInputStream.newInstance(data);
mergeFrom(input);
@@ -578,6 +593,7 @@ public final class UnknownFieldSet implements MessageLite {
* set being built. This is just a small wrapper around
* {@link #mergeFrom(CodedInputStream)}.
*/
+ @Override
public Builder mergeFrom(final InputStream input) throws IOException {
final CodedInputStream codedInput = CodedInputStream.newInstance(input);
mergeFrom(codedInput);
@@ -585,8 +601,8 @@ public final class UnknownFieldSet implements MessageLite {
return this;
}
- public boolean mergeDelimitedFrom(InputStream input)
- throws IOException {
+ @Override
+ public boolean mergeDelimitedFrom(InputStream input) throws IOException {
final int firstByte = input.read();
if (firstByte == -1) {
return false;
@@ -597,30 +613,29 @@ public final class UnknownFieldSet implements MessageLite {
return true;
}
- public boolean mergeDelimitedFrom(
- InputStream input,
- ExtensionRegistryLite extensionRegistry) throws IOException {
+ @Override
+ public boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
// UnknownFieldSet has no extensions.
return mergeDelimitedFrom(input);
}
- public Builder mergeFrom(
- CodedInputStream input,
- ExtensionRegistryLite extensionRegistry) throws IOException {
+ @Override
+ public Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
// UnknownFieldSet has no extensions.
return mergeFrom(input);
}
- public Builder mergeFrom(
- ByteString data,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
// UnknownFieldSet has no extensions.
return mergeFrom(data);
}
- public Builder mergeFrom(byte[] data, int off, int len)
- throws InvalidProtocolBufferException {
+ @Override
+ public Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException {
try {
final CodedInputStream input =
CodedInputStream.newInstance(data, off, len);
@@ -636,29 +651,37 @@ public final class UnknownFieldSet implements MessageLite {
}
}
- public Builder mergeFrom(
- byte[] data,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
// UnknownFieldSet has no extensions.
return mergeFrom(data);
}
- public Builder mergeFrom(
- byte[] data, int off, int len,
- ExtensionRegistryLite extensionRegistry)
+ @Override
+ public Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
// UnknownFieldSet has no extensions.
return mergeFrom(data, off, len);
}
- public Builder mergeFrom(
- InputStream input,
- ExtensionRegistryLite extensionRegistry) throws IOException {
+ @Override
+ public Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
+ throws IOException {
// UnknownFieldSet has no extensions.
return mergeFrom(input);
}
+ @Override
+ public Builder mergeFrom(MessageLite m) {
+ if (m instanceof UnknownFieldSet) {
+ return mergeFrom((UnknownFieldSet) m);
+ }
+ throw new IllegalArgumentException(
+ "mergeFrom(MessageLite) can only merge messages of the same type.");
+ }
+
+ @Override
public boolean isInitialized() {
// UnknownFieldSets do not have required fields, so they are always
// initialized.
@@ -987,6 +1010,7 @@ public final class UnknownFieldSet implements MessageLite {
* Parser to implement MessageLite interface.
*/
public static final class Parser extends AbstractParser<UnknownFieldSet> {
+ @Override
public UnknownFieldSet parsePartialFrom(
CodedInputStream input, ExtensionRegistryLite extensionRegistry)
throws InvalidProtocolBufferException {
@@ -1004,6 +1028,7 @@ public final class UnknownFieldSet implements MessageLite {
}
private static final Parser PARSER = new Parser();
+ @Override
public final Parser getParserForType() {
return PARSER;
}
diff --git a/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
index 5257c5a2..30e87911 100644
--- a/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
+++ b/java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java
@@ -68,42 +68,42 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
return list.size();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public ByteString getByteString(int index) {
return list.getByteString(index);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void add(ByteString element) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void set(int index, ByteString element) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean addAllByteString(Collection<? extends ByteString> element) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public byte[] getByteArray(int index) {
return list.getByteArray(index);
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void add(byte[] element) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void set(int index, byte[] element) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean addAllByteArray(Collection<byte[]> element) {
throw new UnsupportedOperationException();
}
@@ -113,47 +113,47 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
return new ListIterator<String>() {
ListIterator<String> iter = list.listIterator(index);
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasNext() {
return iter.hasNext();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public String next() {
return iter.next();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasPrevious() {
return iter.hasPrevious();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public String previous() {
return iter.previous();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public int nextIndex() {
return iter.nextIndex();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public int previousIndex() {
return iter.previousIndex();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void set(String o) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void add(String o) {
throw new UnsupportedOperationException();
}
@@ -165,45 +165,45 @@ public class UnmodifiableLazyStringList extends AbstractList<String>
return new Iterator<String>() {
Iterator<String> iter = list.iterator();
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public boolean hasNext() {
return iter.hasNext();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public String next() {
return iter.next();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public List<?> getUnderlyingElements() {
// The returned value is already unmodifiable.
return list.getUnderlyingElements();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public void mergeFrom(LazyStringList other) {
throw new UnsupportedOperationException();
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public List<byte[]> asByteArrayList() {
return Collections.unmodifiableList(list.asByteArrayList());
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public List<ByteString> asByteStringList() {
return Collections.unmodifiableList(list.asByteStringList());
}
- //@Override (Java 1.6 override semantics, but we must support 1.5)
+ @Override
public LazyStringList getUnmodifiableView() {
return this;
}
diff --git a/java/core/src/main/java/com/google/protobuf/WireFormat.java b/java/core/src/main/java/com/google/protobuf/WireFormat.java
index 8dbe1ae3..6a58b081 100644
--- a/java/core/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/WireFormat.java
@@ -116,16 +116,24 @@ public final class WireFormat {
FIXED32 (JavaType.INT , WIRETYPE_FIXED32 ),
BOOL (JavaType.BOOLEAN , WIRETYPE_VARINT ),
STRING (JavaType.STRING , WIRETYPE_LENGTH_DELIMITED) {
- public boolean isPackable() { return false; }
+ @Override
+ public boolean isPackable() {
+ return false; }
},
GROUP (JavaType.MESSAGE , WIRETYPE_START_GROUP ) {
- public boolean isPackable() { return false; }
+ @Override
+ public boolean isPackable() {
+ return false; }
},
MESSAGE (JavaType.MESSAGE , WIRETYPE_LENGTH_DELIMITED) {
- public boolean isPackable() { return false; }
+ @Override
+ public boolean isPackable() {
+ return false; }
},
BYTES (JavaType.BYTE_STRING, WIRETYPE_LENGTH_DELIMITED) {
- public boolean isPackable() { return false; }
+ @Override
+ public boolean isPackable() {
+ return false; }
},
UINT32 (JavaType.INT , WIRETYPE_VARINT ),
ENUM (JavaType.ENUM , WIRETYPE_VARINT ),
@@ -170,18 +178,21 @@ public final class WireFormat {
enum Utf8Validation {
/** Eagerly parses to String; silently accepts invalid UTF8 bytes. */
LOOSE {
+ @Override
Object readString(CodedInputStream input) throws IOException {
return input.readString();
}
},
/** Eagerly parses to String; throws an IOException on invalid bytes. */
STRICT {
+ @Override
Object readString(CodedInputStream input) throws IOException {
return input.readStringRequireUtf8();
}
},
/** Keep data as ByteString; validation/conversion to String is lazy. */
LAZY {
+ @Override
Object readString(CodedInputStream input) throws IOException {
return input.readBytes();
}